<!DOCTYPE html>

<html lang="zh-CN">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>甘蔗农机智能管控平台V1.0</title>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script>

    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"/>

    <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>

    <script src="/static/echarts.min.js"></script>

    <style>

        * { margin: 0; padding: 0; box-sizing: border-box; }

        
        
        body {

            font-family: 'Microsoft YaHei', Arial, sans-serif;

            background: #f5f7fa;

            height: 100vh;

            overflow: hidden;

        }

        
        
        /* ========== 顶部栏 ========== */

        .top-header {

            height: 65px;

            background: #2c3e50;

            color: white;

            display: flex;

            align-items: center;

            justify-content: space-between;

            padding: 0 25px;

            box-shadow: 0 2px 4px rgba(0,0,0,0.1);

        }

        
        
        .title {

            font-size: 20px;

            font-weight: 600;

        }

        
        
        .header-center {

            display: flex;

            gap: 30px;

        }

        
        
        .header-item {

            display: flex;

            align-items: center;

            gap: 8px;

        }

        
        
        .header-item label {

            color: #95a5a6;

            font-size: 14px;

        }

        
        
        .header-item span, .header-item select {

            color: white;

            font-weight: 500;

        }

        
        
        select {

            background: white;

            color: #2c3e50;

            border: 1px solid #bdc3c7;

            padding: 5px 10px;

            border-radius: 4px;

            cursor: pointer;

        }
        
        select option {
            background: white;
            color: #2c3e50;
            padding: 8px;
        }
        
        /* 顶部select特殊样式 */
        .header-item select {
            background: #34495e;
            color: white;
            border: 1px solid #3498db;
        }

        
        
        /* ========== 主布局 ========== */

        .main-layout {

            display: flex;

            height: calc(100vh - 65px);

        }

        
        
        /* 左侧导航 */

        .sidebar {

            width: 160px;

            background: #34495e;

            display: flex;

            flex-direction: column;

        }

        
        
        .nav-list {

            flex: 1;

        }

        
        
        .nav-item {

            padding: 20px 15px;

            text-align: center;

            color: #bdc3c7;

            cursor: pointer;

            border-bottom: 1px solid #2c3e50;

            font-size: 14px;

            transition: all 0.2s;

        }

        
        
        .nav-item:hover {

            background: #2c3e50;

            color: white;

        }

        
        
        .nav-item.active {

            background: #3498db;

            color: white;

            border-left: 4px solid #2ecc71;

        }

        
        
        .sidebar-footer {

            padding: 15px;

            background: #2c3e50;

            font-size: 12px;

            color: #95a5a6;

            border-top: 1px solid #1a252f;

        }

        
        
        /* 中间内容区 */

        .content-wrapper {

            flex: 1;

            display: flex;

            flex-direction: column;

            overflow: hidden;

        }

        
        
        /* 视频区 */

        .video-area {

            height: 350px;

            display: grid;

            grid-template-columns: 1fr 1fr;

            gap: 10px;

            padding: 10px;

            background: #ecf0f1;

        }

        
        
        .video-box {

            position: relative;

            background: #000;

            border-radius: 4px;

            overflow: hidden;

            border: 2px solid #bdc3c7;

        }

        
        
        .video-box img {

            width: 100%;

            height: 100%;

            object-fit: cover;

        }

        
        
        .video-label {

            position: absolute;

            top: 10px;

            left: 10px;

            background: rgba(0,0,0,0.8);

            color: #2ecc71;

            padding: 6px 12px;

            border-radius: 4px;

            font-size: 13px;

            font-weight: 500;

        }

        
        
        /* 页面容器 */

        .page-container {

            flex: 1;

            padding: 10px;

            overflow-y: auto;

            background: #ecf0f1;

        }

        
        
        .page {

            display: none;

            height: 100%;

        }

        
        
        .page.active {

            display: flex;

            flex-direction: column;

            height: 100%;
        }
        
        #page-gis.active {
            display: flex;

            flex-direction: column;

        }

        
        
        /* 内容卡片 */

        .card {

            background: white;

            border-radius: 6px;

            padding: 20px;

            margin-bottom: 10px;

            box-shadow: 0 1px 3px rgba(0,0,0,0.1);

        }

        
        
        .card-title {

            font-size: 17px;

            font-weight: 600;

            color: #2c3e50;

            margin-bottom: 15px;

            padding-bottom: 10px;

            border-bottom: 2px solid #3498db;

        }

        
        
        /* 地图容器 */

        .map-wrapper {

            flex: 1;

            position: relative;

            background: white;

            border-radius: 6px;

            overflow: hidden;

            border: 2px solid #bdc3c7;

        }

        
        
        .map-controls {

            position: absolute;

            top: 15px;

            right: 15px;

            z-index: 1000;

        }

        
        
        .map-btn {

            background: #3498db;

            color: white;

            border: none;

            padding: 10px 16px;

            border-radius: 4px;

            cursor: pointer;

            font-size: 13px;

            box-shadow: 0 2px 4px rgba(0,0,0,0.2);

            transition: all 0.2s;

        }

        
        
        .map-btn:hover {

            background: #2980b9;

        }

        
        
        /* 按钮组 */

        .action-bar {

            display: flex;

            gap: 10px;

            margin-top: 10px;

        }

        
        
        .btn {

            flex: 1;

            padding: 14px;

            border: none;

            border-radius: 4px;

            font-size: 14px;

            font-weight: 600;

            cursor: pointer;

            transition: all 0.2s;

        }

        
        
        .btn-primary {

            background: #3498db;

            color: white;

        }

        
        
        .btn-success {

            background: #27ae60;

            color: white;

        }

        
        
        .btn-warning {

            background: #f39c12;

            color: white;

        }

        
        
        .btn-danger {

            background: #e74c3c;

            color: white;

        }

        
        
        .btn-default {

            background: #95a5a6;

            color: white;

        }

        
        
        .btn:hover {

            opacity: 0.9;

            transform: translateY(-1px);

        }

        
        
        /* 右侧面板 */

        .right-panel {

            width: 320px;

            background: white;

            border-left: 2px solid #bdc3c7;

            overflow-y: auto;

            transition: width 0.3s ease;

            position: relative;

        }

        

        .right-panel.expanded {

            width: 960px;

        }

        
        
        .panel-header {

            background: #3498db;

            color: white;

            padding: 15px;

            font-size: 15px;

            font-weight: 600;

            text-align: center;

            position: relative;

            display: flex;

            align-items: center;

            justify-content: center;

        }

        

        .panel-toggle-btn {

            position: absolute;

            left: 15px;

            background: rgba(255,255,255,0.2);

            border: 1px solid rgba(255,255,255,0.5);

            color: white;

            padding: 5px 10px;

            border-radius: 4px;

            cursor: pointer;

            font-size: 13px;

            transition: all 0.2s;

        }

        

        .panel-toggle-btn:hover {

            background: rgba(255,255,255,0.3);

            transform: scale(1.05);

        }

        

        .robots-container {

            display: none;

        }

        

        .right-panel.expanded .robots-container {

            display: flex;

            flex-wrap: wrap;

            gap: 10px;

            padding: 15px;

        }

        

        .right-panel.expanded .single-robot {

            display: none;

        }

        

        .robot-card {

            flex: 0 0 calc(33.333% - 10px);

            background: #f8f9fa;

            border: 2px solid #e3e3e3;

            border-radius: 8px;

            padding: 10px;

            box-sizing: border-box;

        }

        

        .robot-card-header {

            background: #34495e;

            color: white;

            padding: 8px;

            border-radius: 4px;

            font-size: 13px;

            font-weight: 600;

            text-align: center;

            margin-bottom: 10px;

        }

        

        .robot-card .panel-section {

            padding: 8px;

            border-bottom: 1px solid #dee2e6;

        }

        

        .robot-card .section-title {

            font-size: 12px;

            margin-bottom: 8px;

            padding-bottom: 4px;

        }

        

        .robot-card .info-row {

            padding: 4px 0;

            font-size: 11px;

        }

        

        .robot-card .progress {

            height: 16px;

            margin-top: 4px;

        }

        

        .robot-card .progress-bar {

            font-size: 10px;

            line-height: 16px;

        }

        
        
        .panel-section {

            padding: 15px;

            border-bottom: 1px solid #ecf0f1;

        }

        
        
        .section-title {

            font-size: 14px;

            font-weight: 600;

            color: #2c3e50;

            margin-bottom: 12px;

            padding-bottom: 6px;

            border-bottom: 2px solid #3498db;

        }

        
        
        .info-row {

            display: flex;

            justify-content: space-between;

            padding: 8px 0;

            font-size: 13px;

            color: #7f8c8d;

        }

        
        
        .info-value {

            color: #27ae60;

            font-weight: 600;

        }

        
        
        /* 进度条 */

        .progress {

            height: 22px;

            background: #ecf0f1;

            border-radius: 11px;

            overflow: hidden;

            margin-top: 8px;

        }

        
        
        .progress-bar {

            height: 100%;

            background: #27ae60;

            color: white;

            display: flex;

            align-items: center;

            justify-content: center;

            font-size: 12px;

            font-weight: 600;

            transition: width 0.3s;

        }

        
        
        /* ========== 弹窗 ========== */

        .modal-overlay {

            display: none;

            position: fixed;

            top: 0;

            left: 0;

            width: 100%;

            height: 100%;

            background: rgba(0,0,0,0);
            z-index: 9998;

            transition: background 0.3s ease;
        }
        
        .modal-overlay.show {
            background: rgba(0,0,0,0.6);
        }

        
        
        .modal {

            display: none;

            position: fixed;

            top: 50%;

            left: 50%;

            transform: translate(-50%, -60%);
            background: white;

            border-radius: 8px;

            padding: 0;

            min-width: 600px;

            max-width: 85%;

            max-height: 85vh;

            z-index: 9999;

            box-shadow: 0 8px 32px rgba(0,0,0,0.2);

            border: 2px solid #3498db;

            opacity: 0;
            transition: all 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
        }
        
        .modal.show {
            opacity: 1;
            transform: translate(-50%, -50%);
        }

        
        
        .modal-header {

            background: #3498db;

            color: white;

            padding: 18px 25px;

            font-size: 18px;

            font-weight: 600;

            border-radius: 6px 6px 0 0;

            display: flex;

            justify-content: space-between;

            align-items: center;

        }

        
        
        .modal-close {

            background: white;

            color: #e74c3c;

            border: none;

            width: 30px;

            height: 30px;

            border-radius: 50%;

            cursor: pointer;

            font-size: 20px;

            font-weight: bold;

            line-height: 1;

        }

        
        
        .modal-close:hover {

            background: #ecf0f1;

        }

        
        
        .modal-body {

            padding: 25px;

            max-height: calc(85vh - 70px);

            overflow-y: auto;

        }

        
        
        /* 弹窗内元素 */

        .modal-grid {

            display: grid;

            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));

            gap: 15px;

            margin: 20px 0;

        }

        
        
        .modal-card {

            background: #f8f9fa;

            padding: 20px;

            border-radius: 6px;

            text-align: center;

            border: 1px solid #e0e0e0;

        }

        
        
        .modal-card-label {

            color: #7f8c8d;

            font-size: 13px;

            margin-bottom: 10px;

        }

        
        
        .modal-card-value {

            color: #3498db;

            font-size: 32px;

            font-weight: 700;

        }

        
        
        .modal-card-unit {

            color: #95a5a6;

            font-size: 12px;

            margin-top: 5px;

        }

        
        
        .modal-progress {

            margin: 20px 0;

        }

        
        
        .modal-progress-label {

            color: #7f8c8d;

            font-size: 14px;

            margin-bottom: 8px;

        }

        
        
        .modal-progress-bar {

            height: 32px;

            background: #ecf0f1;

            border-radius: 16px;

            overflow: hidden;

        }

        
        
        .modal-progress-fill {

            height: 100%;

            background: #3498db;

            display: flex;

            align-items: center;

            justify-content: center;

            color: white;

            font-weight: 600;

            font-size: 14px;

            transition: width 0.4s;

        }

        
        
        .log-panel {

            background: #1e1e1e;

            color: #00ff00;

            padding: 15px;

            border-radius: 6px;

            height: 220px;

            overflow-y: auto;

            font-family: 'Courier New', monospace;

            font-size: 12px;

            line-height: 1.5;

        }

        
        
        .log-line {

            margin-bottom: 3px;

        }

        
        
        .modal-buttons {

            display: flex;

            gap: 10px;

            margin-top: 25px;

        }

        
        
        .modal-btn {

            flex: 1;

            padding: 12px 20px;

            border: none;

            border-radius: 4px;

            font-size: 14px;

            font-weight: 600;

            cursor: pointer;

            transition: all 0.2s;

        }

        
        
        .modal-btn:hover {

            opacity: 0.9;

        }

        
        
        .spinner {

            width: 50px;

            height: 50px;

            border: 5px solid #ecf0f1;

            border-top-color: #3498db;

            border-radius: 50%;

            animation: spin 1s linear infinite;

            margin: 30px auto;

        }

        
        
        @keyframes spin {

            to { transform: rotate(360deg); }

        }

        
        
        /* 表格 */

        .data-table {

            width: 100%;

            border-collapse: collapse;

            margin-top: 15px;

        }

        
        
        .data-table thead tr {

            background: #ecf0f1;

            border-bottom: 2px solid #3498db;

        }

        
        
        .data-table th {

            padding: 12px;

            text-align: left;

            font-weight: 600;

            color: #2c3e50;

            font-size: 13px;

        }

        
        
        .data-table td {

            padding: 12px;

            border-bottom: 1px solid #ecf0f1;

            color: #7f8c8d;

            font-size: 13px;

        }

        
        
        .data-table tr:hover {

            background: #f8f9fa;

        }

        
        
        /* 状态标签 */

        .badge {

            display: inline-block;

            padding: 4px 10px;

            border-radius: 12px;

            font-size: 12px;

            font-weight: 600;

        }

        
        
        .badge-success {

            background: #d5f4e6;

            color: #27ae60;

        }

        
        
        .badge-warning {

            background: #fdebd0;

            color: #f39c12;

        }

        
        
        .badge-danger {

            background: #fadbd8;

            color: #e74c3c;

        }

        
        
        .badge-info {

            background: #d6eaf8;

            color: #3498db;

        }

        
        
        /* 算法卡片 */

        .algo-cards {

            display: grid;

            grid-template-columns: repeat(3, 1fr);

            gap: 15px;

        }

        
        
        .algo-card {

            padding: 30px 20px;

            border-radius: 6px;

            text-align: center;

            color: white;

            cursor: pointer;

            transition: all 0.2s;

        }

        
        
        .algo-card:hover {

            transform: translateY(-3px);

            box-shadow: 0 8px 16px rgba(0,0,0,0.2);

        }

        
        
        .algo-card h4 {

            font-size: 17px;

            margin-bottom: 10px;

        }

        
        
        .algo-card p {

            font-size: 13px;

            opacity: 0.95;

            margin-bottom: 15px;

        }

        
        
        .algo-meta {

            background: rgba(255,255,255,0.2);

            padding: 8px;

            border-radius: 4px;

            font-size: 12px;

        }

        
        
        /* 通讯模块卡片 */

        .comm-grid {

            display: grid;

            grid-template-columns: repeat(2, 1fr);

            gap: 15px;

        }

        
        
        .comm-card {

            background: #f8f9fa;

            padding: 20px;

            border-radius: 6px;

            border-left: 4px solid #3498db;

        }

        
        
        .comm-title {

            font-size: 15px;

            font-weight: 600;

            color: #2c3e50;

            margin-bottom: 12px;

        }

        
        
        .comm-info {

            font-size: 13px;

            color: #7f8c8d;

            line-height: 1.8;

        }

        
        
        /* 统计卡片 */

        .stats-card {

            background: #f8f9fa;

            padding: 20px;

            border-radius: 6px;

            border-left: 4px solid #f39c12;

        }

        
        
        .stats-title {

            font-size: 15px;

            font-weight: 600;

            color: #2c3e50;

            margin-bottom: 15px;

        }

        
        
        .stats-item {

            font-size: 13px;

            color: #7f8c8d;

            line-height: 2;

        }

        
        
        .stats-value {

            font-weight: 700;

            color: #2c3e50;

        }

        
        
        /* Toast提示 */

        .toast {

            position: fixed;

            top: 50%;

            left: 50%;

            transform: translate(-50%, -50%);

            background: white;

            color: #333;

            padding: 18px 35px;

            border-radius: 6px;

            font-size: 15px;

            font-weight: 500;

            z-index: 999999;

            box-shadow: 0 4px 12px rgba(0,0,0,0.15);

            border: 2px solid #3498db;

        }

        
        
        /* 开关 */

        .switch {

            position: relative;

            display: inline-block;

            width: 50px;

            height: 26px;

            background: #ccc;

            border-radius: 13px;

            cursor: pointer;

            transition: background 0.3s;

        }

        
        
        .switch.on {

            background: #27ae60;

        }

        
        
        .switch-handle {

            position: absolute;

            top: 3px;

            left: 3px;

            width: 20px;

            height: 20px;

            background: white;

            border-radius: 50%;

            transition: left 0.3s;

        }

        
        
        .switch.on .switch-handle {

            left: 27px;

        }

        
        
        /* WASD控制 */

        .wasd-display {

            text-align: center;

            padding: 30px;

        }

        
        
        .wasd-values {

            display: flex;

            justify-content: center;

            gap: 60px;

            margin: 20px 0;

        }

        
        
        .value-display {

            text-align: center;

        }

        
        
        .value-label {

            color: #7f8c8d;

            font-size: 14px;

            margin-bottom: 10px;

        }

        
        
        .value-number {

            color: #3498db;

            font-size: 48px;

            font-weight: 700;

        }

    </style>

</head>

<body>

    <div class="top-header">

        <div class="title">甘蔗农机智能管控平台 V1.0</div>

        <div class="header-center">

            <div class="header-item">

                <label>机器人:</label>

                <select id="robot-select">

                    <option value="GZJY001">GZJY001</option>

                    <option value="GZJY002">GZJY002</option>

                </select>

            </div>

            <div class="header-item">

                <label>GPS卫星:</label>

                <span id="top-gps">0</span>

            </div>

            <div class="header-item">

                <label>雷达点数:</label>

                <span id="top-lidar">0</span>

            </div>

        </div>

        <div>

            <span id="clock"></span>

        </div>

    </div>

    
    
    <div class="main-layout">

        <!-- 左侧导航 -->

        <div class="sidebar">

            <div class="nav-list">

                <div class="nav-item active" onclick="switchPage('home')">操作首页</div>

                <div class="nav-item" onclick="switchPage('remote')">远程控制</div>

                <div class="nav-item" onclick="switchPage('algorithm')">算法模块</div>

                <div class="nav-item" onclick="switchPage('gis')">GIS模块</div>

                <div class="nav-item" onclick="switchPage('comm')">通讯模块</div>

                <div class="nav-item" onclick="switchPage('info')">信息管理</div>

                <div class="nav-item" onclick="switchPage('system')">系统服务</div>

            </div>

            <div class="sidebar-footer">

                <div style="margin-bottom: 8px;">当前机器人</div>

                <div style="color: #27ae60; font-weight: 600;" id="sidebar-robot">GZJY001 在线</div>

                <div style="margin-top: 12px; padding-top: 12px; border-top: 1px solid #34495e;">

                    <div style="font-size: 11px;">GZJY002 在线</div>

                </div>

                <div id="task-status-panel" style="margin-top: 15px; padding-top: 15px; border-top: 1px solid #34495e; display: none;">
                    
                    <div style="margin-bottom: 8px; font-size: 12px; color: #95a5a6;">当前任务</div>
                    
                    <div id="task-list-container" style="max-height: 200px; overflow-y: auto;"></div>

                </div>

            </div>

        </div>

        
        
        <!-- 中间内容 -->

        <div class="content-wrapper">

            <!-- 视频区域 -->

            <div class="video-area" id="video-section">

                <div class="video-box">

                    <div class="video-label">前置双光摄像头</div>

                    <img src="/video" onerror="this.src='';">

                </div>

                <div class="video-box">

                    <div class="video-label">后置双光摄像头</div>

                    <img src="/video2" onerror="this.src='';">

                </div>

            </div>

            
            
            <!-- 页面容器 -->

            <div class="page-container">

                <!-- 页面1: 操作首页 -->

                <div class="page active" id="page-home">

                    <div class="map-wrapper">

                        <div class="map-controls">

                            <button class="map-btn" onclick="resetMap()">重置地图</button>

                        </div>

                        <div id="map" style="width:100%; height:100%;"></div>

                    </div>

                    <div class="action-bar">

                        <button class="btn btn-success" onclick="showPathAssignment()">路径任务分配</button>

                        <button class="btn btn-danger" onclick="startWork()">开始作业</button>

                        <button class="btn btn-default" onclick="stopWork()">停止作业</button>

                        <button class="btn btn-default" onclick="showWorkManage()">作业管理</button>

                        <button class="btn btn-default" onclick="showWorkEval()">作业评估</button>

                        <button class="btn btn-default" onclick="generateReport()">作业报告</button>

                    </div>

                </div>

                
                
                <!-- 页面2: 远程控制 -->

                <div class="page" id="page-remote">

                    <div class="card">

                        <div class="card-title">WASD遥控操作</div>

                        <div class="wasd-display">

                            <div style="color: #7f8c8d; margin-bottom: 15px;">使用键盘 W/A/S/D 控制机器人运动</div>

                            <div class="wasd-values">

                                <div class="value-display">

                                    <div class="value-label">前进/后退</div>

                                    <div class="value-number" id="fwd-val">0</div>

                                </div>

                                <div class="value-display">

                                    <div class="value-label">左转/右转</div>

                                    <div class="value-number" id="turn-val">0</div>

                                </div>

                            </div>

                            <div style="color: #95a5a6; font-size: 13px; margin-top: 15px;">

                                提示: 空格键紧急停止 | TAB键切换档位

                            </div>

                        </div>

                    </div>

                    <div class="action-bar">

                        <button class="btn btn-default" onclick="setMode('路径分配')">路径分配</button>

                        <button class="btn btn-default" onclick="setMode('报警处置')">报警处置</button>

                        <button class="btn btn-success" onclick="setMode('手动模式')">手动模式</button>

                        <button class="btn btn-default" onclick="setMode('速度1档')">速度1档</button>

                        <button class="btn btn-default" onclick="setMode('单手模式')">单手模式</button>

                        <button class="btn btn-primary" onclick="showRemoteDetail()">详细操作</button>

                    </div>

                </div>

                
                
                <!-- 页面3: 算法模块 -->

                <div class="page" id="page-algorithm">

                    <div class="card">

                        <div class="card-title">核心算法模块</div>
                        <table class="data-table" style="margin-top: 0;">
                            <thead>
                                <tr>
                                    <th style="width: 180px;">算法名称</th>
                                    <th>算法描述</th>
                                    <th style="width: 140px;">关键指标</th>
                                    <th style="width: 100px;">运行状态</th>
                                    <th style="width: 140px;">操作</th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr>
                                    <td style="font-weight: 600; color: #2c3e50;">甘蔗识别</td>
                                    <td style="color: #7f8c8d;">YOLOv8深度学习模型，实时识别甘蔗茎秆、叶片与割叶位置</td>
                                    <td><span class="badge badge-success">98.7% / 30FPS</span></td>
                                    <td><span class="badge badge-warning" id="algo-status-1">待启动</span></td>
                                    <td><button class="btn btn-primary" style="padding: 6px 12px; font-size: 12px;" onclick="showSugarcaneDet()">详情</button></td>
                                </tr>
                                <tr>
                                    <td style="font-weight: 600; color: #2c3e50;">割叶控制</td>
                                    <td style="color: #7f8c8d;">PID闭环控制，刀具高度与角度实时自适应调节</td>
                                    <td><span class="badge badge-info">±2cm / 30ms</span></td>
                                    <td><span class="badge badge-warning" id="algo-status-2">待启动</span></td>
                                    <td><button class="btn btn-primary" style="padding: 6px 12px; font-size: 12px;" onclick="showLeafCutAlgo()">详情</button></td>
                                </tr>
                                <tr>
                                    <td style="font-weight: 600; color: #2c3e50;">甘蔗行识别</td>
                                    <td style="color: #7f8c8d;">激光雷达与视觉融合，卡尔曼滤波实现高精度行跟踪</td>
                                    <td><span class="badge badge-success">偏差 < 3cm</span></td>
                                    <td><span class="badge badge-warning" id="algo-status-3">待启动</span></td>
                                    <td><button class="btn btn-primary" style="padding: 6px 12px; font-size: 12px;" onclick="showRowDetect()">详情</button></td>
                                </tr>
                                <tr>
                                    <td style="font-weight: 600; color: #2c3e50;">障碍物检测</td>
                                    <td style="color: #7f8c8d;">LD14P激光雷达360°扫描，实时障碍物检测与分类</td>
                                    <td><span class="badge badge-danger">0.2-12m / 8Hz</span></td>
                                    <td><span class="badge badge-warning" id="algo-status-4">待启动</span></td>
                                    <td><button class="btn btn-primary" style="padding: 6px 12px; font-size: 12px;" onclick="showObstacleAvoid()">详情</button></td>
                                </tr>
                                <tr>
                                    <td style="font-weight: 600; color: #2c3e50;">路径规划</td>
                                    <td style="color: #7f8c8d;">A*全局规划与DWA局部规划混合算法</td>
                                    <td><span class="badge badge-warning">60ms / 95%</span></td>
                                    <td><span class="badge badge-warning" id="algo-status-5">待启动</span></td>
                                    <td><button class="btn btn-primary" style="padding: 6px 12px; font-size: 12px;" onclick="showPathPlan()">详情</button></td>
                                </tr>
                                <tr>
                                    <td style="font-weight: 600; color: #2c3e50;">地形自适应</td>
                                    <td style="color: #7f8c8d;">IMU姿态检测，液压系统自动调平与防侧翻控制</td>
                                    <td><span class="badge badge-info">最大 15°</span></td>
                                    <td><span class="badge badge-warning" id="algo-status-6">待启动</span></td>
                                    <td><button class="btn btn-primary" style="padding: 6px 12px; font-size: 12px;" onclick="showTerrainAdapt()">详情</button></td>
                                </tr>
                            </tbody>
                        </table>
                            </div>

                    
                    <div class="card" style="margin-top: 10px;">
                        <div class="card-title">实时性能监控</div>
                        <table class="data-table" style="margin-top: 0;">
                            <thead>
                                <tr>
                                    <th>性能指标</th>
                                    <th style="width: 150px;">当前值</th>
                                    <th style="width: 150px;">标准值</th>
                                    <th>进度</th>
                                    <th style="width: 100px;">状态</th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr>
                                    <td style="font-weight: 600; color: #2c3e50;">甘蔗识别准确率</td>
                                    <td><span style="color: #27ae60; font-weight: 600; font-size: 15px;">98.7%</span></td>
                                    <td><span style="color: #7f8c8d;">≥ 95.0%</span></td>
                                    <td>
                                        <div style="background: #ecf0f1; height: 8px; border-radius: 4px; overflow: hidden;">
                                            <div style="background: #27ae60; height: 100%; width: 98.7%;"></div>
                            </div>

                                    </td>
                                    <td><span class="badge badge-success">优秀</span></td>
                                </tr>
                                <tr>
                                    <td style="font-weight: 600; color: #2c3e50;">刀具响应时间</td>
                                    <td><span style="color: #3498db; font-weight: 600; font-size: 15px;">30 ms</span></td>
                                    <td><span style="color: #7f8c8d;">≤ 50 ms</span></td>
                                    <td>
                                        <div style="background: #ecf0f1; height: 8px; border-radius: 4px; overflow: hidden;">
                                            <div style="background: #3498db; height: 100%; width: 60%;"></div>
                            </div>

                                    </td>
                                    <td><span class="badge badge-success">优秀</span></td>
                                </tr>
                                <tr>
                                    <td style="font-weight: 600; color: #2c3e50;">割叶高度精度</td>
                                    <td><span style="color: #27ae60; font-weight: 600; font-size: 15px;">± 2 cm</span></td>
                                    <td><span style="color: #7f8c8d;">± 3 cm</span></td>
                                    <td>
                                        <div style="background: #ecf0f1; height: 8px; border-radius: 4px; overflow: hidden;">
                                            <div style="background: #27ae60; height: 100%; width: 85%;"></div>
                        </div>

                                    </td>
                                    <td><span class="badge badge-success">优秀</span></td>
                                </tr>
                                <tr>
                                    <td style="font-weight: 600; color: #2c3e50;">行跟踪可靠性</td>
                                    <td><span style="color: #27ae60; font-weight: 600; font-size: 15px;">99.2%</span></td>
                                    <td><span style="color: #7f8c8d;">≥ 98.0%</span></td>
                                    <td>
                                        <div style="background: #ecf0f1; height: 8px; border-radius: 4px; overflow: hidden;">
                                            <div style="background: #27ae60; height: 100%; width: 99.2%;"></div>
                            </div>

                                    </td>
                                    <td><span class="badge badge-success">优秀</span></td>
                                </tr>
                                <tr>
                                    <td style="font-weight: 600; color: #2c3e50;">路径规划耗时</td>
                                    <td><span style="color: #3498db; font-weight: 600; font-size: 15px;">60 ms</span></td>
                                    <td><span style="color: #7f8c8d;">≤ 100 ms</span></td>
                                    <td>
                                        <div style="background: #ecf0f1; height: 8px; border-radius: 4px; overflow: hidden;">
                                            <div style="background: #3498db; height: 100%; width: 70%;"></div>
                        </div>

                                    </td>
                                    <td><span class="badge badge-success">良好</span></td>
                                </tr>
                                <tr>
                                    <td style="font-weight: 600; color: #2c3e50;">系统资源占用</td>
                                    <td><span style="color: #f39c12; font-weight: 600; font-size: 15px;">GPU 68%</span></td>
                                    <td><span style="color: #7f8c8d;">≤ 80%</span></td>
                                    <td>
                                        <div style="background: #ecf0f1; height: 8px; border-radius: 4px; overflow: hidden;">
                                            <div style="background: #f39c12; height: 100%; width: 68%;"></div>
                    </div>

                                    </td>
                                    <td><span class="badge badge-info">正常</span></td>
                                </tr>
                            </tbody>
                        </table>
                </div>

                    
                    <div class="action-bar">
                        <button class="btn btn-success" onclick="startAllAlgorithms()">启动全部算法</button>
                        <button class="btn btn-warning" onclick="stopAllAlgorithms()">停止全部算法</button>
                        <button class="btn btn-primary" onclick="showAlgorithmConfig()">算法配置</button>
                        <button class="btn btn-default" onclick="exportAlgorithmLog()">导出日志</button>
                        <button class="btn btn-default" onclick="resetAlgorithms()">重置参数</button>
                    </div>

                </div>

                
                
                <!-- 页面4: GIS模块 -->

                <div class="page" id="page-gis">

                    <!-- 顶部工具栏 -->
                    <div style="background: white; padding: 12px 15px; border-radius: 4px; margin-bottom: 10px; border: 1px solid #bdc3c7;">
                        <div style="display: flex; gap: 10px; align-items: center;">
                            <!-- 路径选择 -->
                            <select style="flex: 0 0 220px; padding: 10px; border: 1px solid #bdc3c7; border-radius: 4px; background: white; font-size: 13px;">
                                <option value="">选择作业路径</option>
                                <option value="path1">PATH-001 东区1号线 (24点)</option>
                                <option value="path2">PATH-002 西区2号线 (36点)</option>
                                <option value="path3">PATH-003 南区掉头 (18点)</option>
                            </select>

                            
                            <!-- 功能按钮组 -->
                            <button class="btn btn-primary" style="flex: 1; padding: 12px; font-size: 14px;" onclick="drawPath()">绘制路径</button>
                            <button class="btn btn-success" style="flex: 1; padding: 12px; font-size: 14px;" onclick="autoPlanning()">自动规划</button>
                            <button class="btn btn-default" style="flex: 1; padding: 12px; font-size: 14px;" onclick="exportPath()">导出路径</button>
                            <button class="btn btn-warning" style="flex: 1; padding: 12px; font-size: 14px;" onclick="loadGISMap()">获取地图</button>
                            <button class="btn btn-default" style="flex: 0 0 auto; padding: 12px 20px; font-size: 14px;" onclick="showGISMenu()">更多</button>
                        </div>

                            </div>

                    
                    <!-- 主内容区：左侧信息 + 地图 -->
                    <div style="flex: 1; display: flex; gap: 10px; min-height: 0; overflow: hidden;">
                        <!-- 左侧路径列表面板 -->
                        <div style="flex: 0 0 280px; background: white; border-radius: 4px; border: 1px solid #bdc3c7; display: flex; flex-direction: column; overflow: hidden;">
                            <div style="background: #3498db; color: white; padding: 12px 15px; font-weight: 600; font-size: 14px; border-radius: 4px 4px 0 0; flex-shrink: 0;">
                                路径与地块管理
                        </div>

                            
                            <div style="flex: 1; overflow-y: auto; padding: 10px;">
                                <!-- 路径列表 -->
                                <div style="margin-bottom: 15px;">
                                    <div style="font-size: 12px; color: #7f8c8d; margin-bottom: 8px; font-weight: 600; padding: 5px 8px; background: #f8f9fa; border-radius: 3px;">
                                        作业路径 (<span id="gis-path-count">0</span>)
                                    </div>
                                    <div id="gis-path-list">
                                        <div style="color: #7f8c8d; padding: 15px; text-align: center; font-size: 12px;">
                                            点击"获取地图"加载路径
                                        </div>
                    </div>
                </div>

                                
                                <!-- 地块列表 -->
                                <div style="margin-bottom: 15px;">
                                    <div style="font-size: 12px; color: #7f8c8d; margin-bottom: 8px; font-weight: 600; padding: 5px 8px; background: #f8f9fa; border-radius: 3px;">作业地块 (3)</div>
                                    <div id="gis-field-list">
                                        <div style="color: #7f8c8d; padding: 15px; text-align: center; font-size: 12px;">
                                            加载地块数据中...
                                        </div>
                                    </div>
                                </div>
                                
                                <!-- 快捷操作 -->
                                <div>
                                    <div style="font-size: 12px; color: #7f8c8d; margin-bottom: 8px; font-weight: 600; padding: 5px 8px; background: #f8f9fa; border-radius: 3px;">快捷操作</div>
                                    <button class="btn btn-success" style="width: 100%; margin-bottom: 6px; padding: 8px; font-size: 12px;" onclick="createNewPath()">新建路径</button>
                                    <button class="btn btn-warning" style="width: 100%; margin-bottom: 6px; padding: 8px; font-size: 12px;" onclick="createNewField()">新建地块</button>
                                    <button class="btn btn-primary" style="width: 100%; margin-bottom: 6px; padding: 8px; font-size: 12px;" onclick="refreshAllGISData()">刷新数据</button>
                                </div>
                            </div>
                        </div>
                        
                        <!-- 地图区域 -->
                        <div style="flex: 1; position: relative; background: #d8d8d8; border-radius: 4px; overflow: hidden; border: 1px solid #bdc3c7; min-width: 0; min-height: 0;">
                            <!-- Leaflet地图容器 -->
                            <div id="gis-map" style="width: 100%; height: 100%; position: absolute; top: 0; left: 0;"></div>
                            
                            <!-- 右侧垂直按钮组 -->
                            <div style="position: absolute; top: 15px; right: 15px; display: flex; flex-direction: column; gap: 10px; z-index: 1000;">
                                <button style="width: 45px; height: 45px; background: #3498db; color: white; border: none; border-radius: 4px; font-size: 20px; cursor: pointer; display: flex; align-items: center; justify-content: center; box-shadow: 0 2px 4px rgba(0,0,0,0.2);" onclick="gisZoomIn()">+</button>
                                <button style="width: 45px; height: 45px; background: #3498db; color: white; border: none; border-radius: 4px; font-size: 20px; cursor: pointer; display: flex; align-items: center; justify-content: center; box-shadow: 0 2px 4px rgba(0,0,0,0.2);" onclick="gisZoomOut()">-</button>
                                <button style="width: 45px; height: 45px; background: #3498db; color: white; border: none; border-radius: 4px; font-size: 20px; cursor: pointer; display: flex; align-items: center; justify-content: center; box-shadow: 0 2px 4px rgba(0,0,0,0.2);" onclick="gisResetView()">⊙</button>
                            </div>
                            
                            <!-- 左上角图例 -->
                            <div style="position: absolute; top: 15px; left: 15px; background: white; padding: 10px 12px; border-radius: 4px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); font-size: 12px; z-index: 1000;">
                                <div style="font-weight: 600; color: #2c3e50; margin-bottom: 8px;">图例</div>
                                <div style="display: flex; align-items: center; margin-bottom: 5px;">
                                    <div style="width: 8px; height: 8px; background: #e74c3c; border-radius: 50%; margin-right: 8px;"></div>
                                    <span style="color: #7f8c8d;">当前位置</span>
                                </div>
                                <div style="display: flex; align-items: center; margin-bottom: 5px;">
                                    <div style="width: 20px; height: 3px; background: #3498db; margin-right: 8px;"></div>
                                    <span style="color: #7f8c8d;">GPS轨迹</span>
                                </div>
                                <div style="display: flex; align-items: center; margin-bottom: 5px;">
                                    <div style="width: 20px; height: 3px; background: #27ae60; margin-right: 8px;"></div>
                                    <span style="color: #7f8c8d;">作业路径</span>
                                </div>
                                <div style="display: flex; align-items: center;">
                                    <div style="width: 20px; height: 3px; background: #f39c12; border-style: dashed; margin-right: 8px;"></div>
                                    <span style="color: #7f8c8d;">绘制中</span>
                                </div>
                            </div>
                            
                            <!-- 绘制状态指示器 -->
                            <div id="draw-indicator" style="display: none; position: absolute; bottom: 15px; left: 50%; transform: translateX(-50%); background: #27ae60; color: white; padding: 10px 18px; border-radius: 4px; box-shadow: 0 2px 6px rgba(0,0,0,0.2); font-size: 13px; z-index: 1000;">
                                <div style="display: flex; align-items: center; gap: 15px;">
                                    <div style="flex: 1;">
                                        <div style="margin-bottom: 4px;">绘制模式: 点击地图添加路径点 | 右键撤销</div>
                                        <div style="font-size: 12px;">已添加 <span id="draw-count">0</span> 个点</div>
                                    </div>
                                    <div style="display: flex; gap: 6px; border-left: 1px solid rgba(255,255,255,0.3); padding-left: 12px;">
                                        <button id="finish-btn" onclick="if(!this.disabled){finishDrawing();this.disabled=true;setTimeout(()=>this.disabled=false,3000);}" style="padding: 6px 14px; background: #fff; color: #27ae60; border: none; border-radius: 3px; cursor: pointer; font-size: 12px;">完成</button>
                                        <button onclick="undoLastPoint()" style="padding: 6px 14px; background: #f39c12; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 12px;">撤销</button>
                                        <button onclick="cancelDrawing()" style="padding: 6px 14px; background: #e74c3c; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 12px;">取消</button>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                    
                    <!-- 底部信息栏 -->
                    <div style="margin-top: 10px; background: white; padding: 15px; border-radius: 4px; border: 1px solid #bdc3c7;">
                        <!-- 第一行：基本信息 -->
                        <div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 25px; margin-bottom: 12px; padding-bottom: 12px; border-bottom: 1px solid #ecf0f1;">
                            <div style="display: flex; align-items: center; gap: 10px;">
                                <div style="font-size: 11px; color: #7f8c8d; min-width: 85px;">地图创建日期:</div>
                                <div style="font-size: 13px; color: #2c3e50; font-weight: 600;" id="map-create-date">-- -- --</div>
                            </div>
                            <div style="display: flex; align-items: center; gap: 10px;">
                                <div style="font-size: 11px; color: #7f8c8d; min-width: 50px;">创建者:</div>
                                <div style="font-size: 13px; color: #2c3e50; font-weight: 600;" id="map-creator">-- -- --</div>
                            </div>
                            <div style="display: flex; align-items: center; gap: 10px;">
                                <div style="font-size: 11px; color: #7f8c8d; min-width: 90px;">创建位置信息:</div>
                                <div style="font-size: 13px; color: #2c3e50; font-weight: 600;" id="map-location">-- -- --</div>
                            </div>
                        </div>
                        
                        <!-- 第二行：路径和任务 -->
                        <div style="display: flex; gap: 30px; font-size: 13px;">
                            <div style="flex: 1;">
                                <span style="color: #7f8c8d; font-size: 12px;">当前地图路径:</span>
                                <div style="margin-top: 6px; display: flex; gap: 12px; flex-wrap: wrap;">
                                    <a href="#" onclick="selectRobotPath(1); return false;" style="color: #3498db; text-decoration: none; font-weight: 600; font-size: 13px;">机器人GZJY001_1号线</a>
                                    <a href="#" onclick="selectRobotPath(2); return false;" style="color: #27ae60; text-decoration: none; font-weight: 600; font-size: 13px;">机器人GZJY002_2号线</a>
                                </div>
                            </div>
                            <div style="flex: 0 0 auto; padding-left: 30px; border-left: 1px solid #ecf0f1;">
                                <span style="color: #7f8c8d; font-size: 12px;">当前任务列表:</span>
                                <div style="margin-top: 6px;">
                                    <a href="#" onclick="selectTask(1); return false;" style="color: #f39c12; text-decoration: none; font-weight: 600; font-size: 13px;">A001_直线操作</a>
                                </div>
                            </div>
                        </div>
                    </div>

                </div>

                
                
                <!-- 页面5: 通讯模块 -->

                <div class="page" id="page-comm">

                    <div class="card">

                        <div class="card-title">通讯模块状态监控</div>

                        <div class="comm-grid">

                            <div class="comm-card" style="border-left-color: #3498db;">

                                <div class="comm-title">TCP/IP连接</div>

                                <div class="comm-info">

                                    <div>状态: <span class="badge badge-success">已连接</span></div>

                                    <div>IP地址: 192.168.10.100</div>

                                    <div>延迟: 10ms</div>

                                </div>

                            </div>

                            <div class="comm-card" style="border-left-color: #9b59b6;">

                                <div class="comm-title">Modbus/RS485</div>

                                <div class="comm-info">

                                    <div>状态: <span class="badge badge-success">正常</span></div>

                                    <div>地址: 0x01</div>

                                    <div>波特率: 9600</div>

                                </div>

                            </div>

                            <div class="comm-card" style="border-left-color: #27ae60;">

                                <div class="comm-title">北斗GPS</div>

                                <div class="comm-info">

                                    <div>状态: <span class="badge badge-success">GPS Fix</span></div>

                                    <div>卫星数: <span id="gps-sats">0</span></div>

                                    <div>端口: /dev/ttyUSB1</div>

                                </div>

                            </div>

                            <div class="comm-card" style="border-left-color: #e74c3c;">

                                <div class="comm-title">激光雷达</div>

                                <div class="comm-info">

                                    <div>状态: <span class="badge badge-success">工作中</span></div>

                                    <div>型号: LD14P</div>

                                    <div>端口: /dev/ttyACM0</div>

                                </div>

                            </div>

                        </div>

                        <div style="margin-top: 15px; background: #e8f5e9; padding: 15px; border-radius: 6px; border-left: 4px solid #27ae60;">

                            <div style="font-weight: 600; color: #27ae60; margin-bottom: 8px;">通讯诊断</div>

                            <div style="color: #27ae60; font-size: 13px;">所有通讯模块工作正常，数据传输稳定</div>

                        </div>

                    </div>

                    <div class="action-bar">

                        <button class="btn btn-primary" onclick="testConnection()">连接测试</button>

                        <button class="btn btn-warning" onclick="restartModbus()">重启Modbus</button>

                        <button class="btn btn-default" onclick="showCommLog()">查看日志</button>

                        <button class="btn btn-default" onclick="diagNetwork()">网络诊断</button>

                        <button class="btn btn-default" onclick="setCommParams()">参数设置</button>

                    </div>

                </div>

                
                
                <!-- 页面6: 信息管理 -->

                <div class="page" id="page-info">

                    <div class="card">

                        <div class="card-title">作业信息统计</div>

                        <div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 15px; margin-bottom: 20px;">

                            <div class="stats-card" style="border-left-color: #f39c12;">

                                <div class="stats-title">作业统计</div>

                                <div class="stats-item">

                                    <div>总作业次数: <span class="stats-value">135 次</span></div>

                                    <div>累计时间: <span class="stats-value">426.8 小时</span></div>

                                    <div>累计面积: <span class="stats-value">1,628 亩</span></div>

                                    <div>平均效率: <span class="stats-value">3.8 亩/小时</span></div>

                                </div>

                            </div>

                            <div class="stats-card" style="border-left-color: #27ae60;">

                                <div class="stats-title">维护记录</div>

                                <div class="stats-item">

                                    <div>上次维护: <span class="stats-value">2024-10-15</span></div>

                                    <div>维护次数: <span class="stats-value">12 次</span></div>

                                    <div>下次维护: <span class="stats-value">2024-11-15</span></div>

                                    <div>健康度: <span class="stats-value" style="color: #27ae60;">92%</span></div>

                                </div>

                            </div>

                        </div>

                        <table class="data-table">

                            <thead>

                                <tr>

                                    <th>日期</th>

                                    <th>机器人</th>

                                    <th>时长</th>

                                    <th>面积</th>

                                    <th>状态</th>

                                </tr>

                            </thead>

                            <tbody>

                                <tr>

                                    <td>2024-10-22</td>

                                    <td>GZJY001</td>

                                    <td>2.5h</td>

                                    <td>9.8亩</td>

                                    <td><span class="badge badge-success">已完成</span></td>

                                </tr>

                                <tr>

                                    <td>2024-10-21</td>

                                    <td>GZJY002</td>

                                    <td>3.2h</td>

                                    <td>12.3亩</td>

                                    <td><span class="badge badge-success">已完成</span></td>

                                </tr>

                                <tr>

                                    <td>2024-10-20</td>

                                    <td>GZJY001</td>

                                    <td>1.8h</td>

                                    <td>7.2亩</td>

                                    <td><span class="badge badge-success">已完成</span></td>

                                </tr>

                            </tbody>

                        </table>

                    </div>

                    <div class="action-bar">

                        <button class="btn btn-primary" onclick="exportDataReport()">导出报表</button>

                        <button class="btn btn-default" onclick="showDetailRecords()">详细记录</button>

                        <button class="btn btn-default" onclick="generateReport()">生成报告</button>

                    </div>

                </div>

                
                
                <!-- 页面7: 系统服务 -->

                <div class="page" id="page-system">

                    <div class="card">

                        <div class="card-title">系统服务管理</div>

                        <div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 15px; margin-bottom: 20px;">

                            <div class="stats-card" style="border-left-color: #3498db;">

                                <div class="stats-title">系统信息</div>

                                <div class="stats-item">

                                    <div>版本: <span class="stats-value">V1.0.0</span></div>

                                    <div>运行时间: <span class="stats-value">72小时</span></div>

                                    <div>系统负载: <span class="stats-value">正常</span></div>

                                    <div>CPU使用: <span class="stats-value">23%</span></div>

                                </div>

                            </div>

                            <div class="stats-card" style="border-left-color: #27ae60;">

                                <div class="stats-title">机器人状态</div>

                                <div class="stats-item">

                                    <div>GZJY001: <span class="badge badge-success">在线</span></div>

                                    <div>GZJY002: <span class="badge badge-success">在线</span></div>

                                    <div>GZJY003: <span class="badge badge-warning">离线</span></div>

                                    <div>总计: <span class="stats-value">2台在线</span></div>

                                </div>

                            </div>

                            <div class="stats-card" style="border-left-color: #f39c12;">

                                <div class="stats-title">服务状态</div>

                                <div class="stats-item">

                                    <div>Web服务: <span class="badge badge-success">运行中</span></div>

                                    <div>数据库: <span class="badge badge-warning">未配置</span></div>

                                    <div>日志服务: <span class="badge badge-success">运行中</span></div>

                                    <div>备份服务: <span class="badge badge-success">运行中</span></div>

                                </div>

                            </div>

                        </div>

                        <div style="background: #e3f2fd; padding: 15px; border-radius: 6px; border-left: 4px solid #2196f3;">

                            <div style="font-weight: 600; color: #1976d2; margin-bottom: 8px;">系统通知</div>

                            <div style="color: #1976d2; font-size: 13px; line-height: 1.8;">

                                系统运行正常，无异常告警<br>

                                建议于 2024-11-15 进行系统维护<br>

                                上次数据备份: 2024-10-21 23:00

                            </div>

                        </div>

                    </div>

                    <div class="action-bar">

                        <button class="btn btn-warning" onclick="restartSystemService()">重启服务</button>

                        <button class="btn btn-default" onclick="showSystemLog()">查看日志</button>

                        <button class="btn btn-primary" onclick="backupData()">备份数据</button>

                        <button class="btn btn-default" onclick="showSystemSettings()">系统设置</button>

                        <button class="btn btn-default" onclick="showAboutSystem()">关于系统</button>

                    </div>

                </div>

            </div>

        </div>

        
        
        <!-- 右侧信息面板 -->

        <div class="right-panel" id="rightPanel">

            <div class="panel-header">
                <button class="panel-toggle-btn" onclick="toggleRightPanel()">
                    <span id="toggleIcon">展开</span>
                </button>
                <span id="panelTitle">机器人 GZJY001 系统状态</span>
            </div>

            <!-- 单机器人视图 -->
            <div class="single-robot">

            
            
            <div class="panel-section">

                <div class="section-title">发电机状态</div>

                <div class="info-row">

                    <span>电压(D129):</span>

                    <span class="info-value" id="voltage">未获取</span>

                </div>

                <div class="info-row">

                    <span>电流(D130):</span>

                    <span class="info-value" id="current">未获取</span>

                </div>

                <div class="info-row">

                    <span>功率(D131):</span>

                    <span class="info-value" id="power">未获取</span>

                </div>

                <div class="info-row">

                    <span>油量(D137):</span>

                    <span class="info-value" id="fuel">未获取</span>

                </div>

                <div class="progress">

                    <div class="progress-bar" id="fuel-bar" style="width: 90%;">90%</div>

                </div>

            </div>

            
            
            <div class="panel-section">

                <div class="section-title">传感器数据</div>

                <div class="info-row"><span>激光测距1:</span><span class="info-value">正常</span></div>

                <div class="info-row"><span>激光测距2:</span><span class="info-value">正常</span></div>

                <div class="info-row"><span>红外传感器1:</span><span class="info-value">正常</span></div>

                <div class="info-row"><span>红外传感器2:</span><span class="info-value">正常</span></div>

                <div class="info-row"><span>温度:</span><span class="info-value" id="temp">42°C</span></div>

            </div>

            
            
            <div class="panel-section">

                <div class="section-title">PLC状态(RS485)</div>

                <div class="info-row"><span>左电机:</span><span class="info-value">正常</span></div>

                <div class="info-row"><span>右电机:</span><span class="info-value">正常</span></div>

                <div class="info-row"><span>左刀具:</span><span class="info-value">正常</span></div>

                <div class="info-row"><span>右刀具:</span><span class="info-value">正常</span></div>

            </div>

            
            
            <div class="panel-section">

                <div class="section-title">通信状态</div>

                <div class="info-row"><span>TCP/IP:</span><span class="info-value">正常</span></div>

                <div class="info-row"><span>Modbus:</span><span class="info-value" id="modbus">正常</span></div>

            </div>

            </div>
            <!-- 结束单机器人视图 -->

            <!-- 多机器人视图 -->
            <div class="robots-container" id="robotsContainer">
                <!-- 机器人1 GZJY001 -->
                <div class="robot-card">
                    <div class="robot-card-header">GZJY001 在线</div>
                    
                    <div class="panel-section">
                        <div class="section-title">发电机状态</div>
                        <div class="info-row"><span>电压:</span><span class="info-value">未获取</span></div>
                        <div class="info-row"><span>油量:</span><span class="info-value">未获取</span></div>
                        <div class="progress">
                            <div class="progress-bar" style="width: 90%;">90%</div>
                        </div>
                    </div>
                    
                    <div class="panel-section">
                        <div class="section-title">传感器数据</div>
                        <div class="info-row"><span>激光测距1:</span><span class="info-value">正常</span></div>
                        <div class="info-row"><span>激光测距2:</span><span class="info-value">正常</span></div>
                        <div class="info-row"><span>红外传感器1:</span><span class="info-value">正常</span></div>
                        <div class="info-row"><span>红外传感器2:</span><span class="info-value">正常</span></div>
                        <div class="info-row"><span>温度:</span><span class="info-value">42°C</span></div>
                    </div>
                    
                    <div class="panel-section">
                        <div class="section-title">PLC状态</div>
                        <div class="info-row"><span>左电机:</span><span class="info-value">正常</span></div>
                        <div class="info-row"><span>右电机:</span><span class="info-value">正常</span></div>
                        <div class="info-row"><span>左刀具:</span><span class="info-value">正常</span></div>
                        <div class="info-row"><span>右刀具:</span><span class="info-value">正常</span></div>
                    </div>
                    
                    <div class="panel-section">
                        <div class="section-title">通信状态</div>
                        <div class="info-row"><span>连接:</span><span class="info-value">连接</span></div>
                        <div class="info-row"><span>TCP/IP:</span><span class="info-value">正常</span></div>
                        <div class="info-row"><span>Modbus:</span><span class="info-value">正常</span></div>
                    </div>
                </div>

                <!-- 机器人2 GZJY002 -->
                <div class="robot-card">
                    <div class="robot-card-header">GZJY002 在线</div>
                    
                    <div class="panel-section">
                        <div class="section-title">发电机状态</div>
                        <div class="info-row"><span>电压:</span><span class="info-value">未获取</span></div>
                        <div class="info-row"><span>油量:</span><span class="info-value">未获取</span></div>
                        <div class="progress">
                            <div class="progress-bar" style="width: 85%;">85%</div>
                        </div>
                    </div>
                    
                    <div class="panel-section">
                        <div class="section-title">传感器数据</div>
                        <div class="info-row"><span>激光测距1:</span><span class="info-value">正常</span></div>
                        <div class="info-row"><span>激光测距2:</span><span class="info-value">正常</span></div>
                        <div class="info-row"><span>红外传感器1:</span><span class="info-value">正常</span></div>
                        <div class="info-row"><span>红外传感器2:</span><span class="info-value">正常</span></div>
                        <div class="info-row"><span>温度:</span><span class="info-value">38°C</span></div>
                    </div>
                    
                    <div class="panel-section">
                        <div class="section-title">PLC状态</div>
                        <div class="info-row"><span>左电机:</span><span class="info-value">正常</span></div>
                        <div class="info-row"><span>右电机:</span><span class="info-value">正常</span></div>
                        <div class="info-row"><span>左刀具:</span><span class="info-value">正常</span></div>
                        <div class="info-row"><span>右刀具:</span><span class="info-value">正常</span></div>
                    </div>
                    
                    <div class="panel-section">
                        <div class="section-title">通信状态</div>
                        <div class="info-row"><span>连接:</span><span class="info-value">连接</span></div>
                        <div class="info-row"><span>TCP/IP:</span><span class="info-value">正常</span></div>
                        <div class="info-row"><span>Modbus:</span><span class="info-value">正常</span></div>
                    </div>
                </div>

                <!-- 机器人3 GZJY003 -->
                <div class="robot-card">
                    <div class="robot-card-header">GZJY003 在线</div>
                    
                    <div class="panel-section">
                        <div class="section-title">发电机状态</div>
                        <div class="info-row"><span>电压:</span><span class="info-value">未获取</span></div>
                        <div class="info-row"><span>油量:</span><span class="info-value">未获取</span></div>
                        <div class="progress">
                            <div class="progress-bar" style="width: 92%;">92%</div>
                        </div>
                    </div>
                    
                    <div class="panel-section">
                        <div class="section-title">传感器数据</div>
                        <div class="info-row"><span>激光测距1:</span><span class="info-value">正常</span></div>
                        <div class="info-row"><span>激光测距2:</span><span class="info-value">正常</span></div>
                        <div class="info-row"><span>红外传感器1:</span><span class="info-value">正常</span></div>
                        <div class="info-row"><span>红外传感器2:</span><span class="info-value">正常</span></div>
                        <div class="info-row"><span>温度:</span><span class="info-value">40°C</span></div>
                    </div>
                    
                    <div class="panel-section">
                        <div class="section-title">PLC状态</div>
                        <div class="info-row"><span>左电机:</span><span class="info-value">正常</span></div>
                        <div class="info-row"><span>右电机:</span><span class="info-value">正常</span></div>
                        <div class="info-row"><span>左刀具:</span><span class="info-value">正常</span></div>
                        <div class="info-row"><span>右刀具:</span><span class="info-value">正常</span></div>
                    </div>
                    
                    <div class="panel-section">
                        <div class="section-title">通信状态</div>
                        <div class="info-row"><span>连接:</span><span class="info-value">连接</span></div>
                        <div class="info-row"><span>TCP/IP:</span><span class="info-value">正常</span></div>
                        <div class="info-row"><span>Modbus:</span><span class="info-value">正常</span></div>
                    </div>
                </div>
            </div>

        </div>

    </div>

    
    
    <!-- 弹窗 -->

    <div class="modal-overlay" id="overlay" onclick="closeModal()"></div>

    <div class="modal" id="modal">

        <div class="modal-header">

            <span id="modal-title">标题</span>

            <button class="modal-close" onclick="closeModal()">×</button>

        </div>

        <div class="modal-body" id="modal-body"></div>

    </div>

    
    
    <script>

        const socket = io();

        let map, marker, trackPath = [], trackPoints = [];

        let wasdState = {forward: 0, turn: 0};

        let activeKeys = new Set();

        
        
        // 时钟

        setInterval(() => {

            const now = new Date();

            document.getElementById('clock').textContent = 

                now.getFullYear() + '年' +

                String(now.getMonth()+1).padStart(2,'0') + '月' +

                String(now.getDate()).padStart(2,'0') + '日 ' +

                String(now.getHours()).padStart(2,'0') + ':' +

                String(now.getMinutes()).padStart(2,'0') + ':' +

                String(now.getSeconds()).padStart(2,'0');

        }, 1000);

        
        
        // 页面切换

        function switchPage(page) {

            // 隐藏所有页面

            document.querySelectorAll('.page').forEach(p => p.classList.remove('active'));

            document.querySelectorAll('.nav-item').forEach(n => n.classList.remove('active'));

            
            
            // 显示目标页面

            const targetPage = document.getElementById('page-' + page);

            if (targetPage) targetPage.classList.add('active');

            
            
            // 高亮导航

            const navs = document.querySelectorAll('.nav-item');

            const pages = ['home', 'remote', 'algorithm', 'gis', 'comm', 'info', 'system'];

            const idx = pages.indexOf(page);

            if (idx >= 0 && navs[idx]) navs[idx].classList.add('active');

            
            
            // 视频区控制（只在home和remote显示）

            const videoSection = document.getElementById('video-section');

            if (videoSection) {

                videoSection.style.display = (page === 'home' || page === 'remote') ? 'grid' : 'none';

            }

            
            // GIS页面切换时，刷新地图显示
            if (page === 'gis' && gisMap) {
                setTimeout(() => {
                    gisMap.invalidateSize();
                }, 100);
            }
            
            // 首页切换时，刷新地图显示
            if (page === 'home' && map) {
                setTimeout(() => {
                    map.invalidateSize();
                }, 100);
            }

        }

        
        
        // 地图初始化

        let gisMap = null;
        let gisMarker = null;
        let gpsTrackLine = null;
        let gpsTrackPoints = [];
        let drawnPaths = {};
        let currentDrawing = null;
        let drawingPoints = [];
        let isDrawingMode = false;
        let fieldCenterMarkers = {};  // 存储地块中心标记
        
        document.addEventListener('DOMContentLoaded', function() {

            // 首页地图
            map = L.map('map').setView([23.757, 109.166], 17);

            L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);

            marker = L.marker([23.757, 109.166]).addTo(map);

            marker.bindPopup('等待GPS定位...');

            trackPath = L.polyline([], {color: '#3498db', weight: 3}).addTo(map);

            // 加载地块到首页地图
            loadFieldsToHomeMap();
            
            setInterval(updateGPS, 2000);

            
            // 初始化GIS地图（延迟加载）
            setTimeout(initGISMap, 1000);
        });
        
        // GIS数据存储
        let gisData = { paths: [], fields: [], settings: {} };
        let pathLayers = {};
        let fieldLayers = {};
        let currentMapId = null;
        let currentMapData = null;
        
        // 首页地图的地块和路径图层
        let homeMapFieldLayers = {};
        let homeMapPathLayers = {};
        
        // 初始化GIS地图
        function initGISMap() {
            if (gisMap) return;
            
            try {
                gisMap = L.map('gis-map').setView([23.757, 109.166], 17);
                L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
                    attribution: '© OpenStreetMap'
                }).addTo(gisMap);
                
                // 加载地块数据
                loadFieldsData();
                
                // 初始化加载路径列表（使用默认地图）
                console.log('[初始化] 加载默认路径列表');
                refreshGISPanel();
                
                // GPS当前位置标记
                gisMarker = L.circleMarker([23.757, 109.166], {
                    radius: 8,
                    fillColor: '#e74c3c',
                    color: '#fff',
                    weight: 2,
                    opacity: 1,
                    fillOpacity: 0.9
                }).addTo(gisMap);
                gisMarker.bindPopup('GPS位置');
                
                // GPS轨迹线
                gpsTrackLine = L.polyline([], {
                    color: '#3498db',
                    weight: 3,
                    opacity: 0.7
                }).addTo(gisMap);
                
                // 地图点击事件（用于绘制路径和地块边界）
                gisMap.on('click', function(e) {
                    console.log('[地图点击] 触发，isDrawingMode=', isDrawingMode, 'latlng=', e.latlng);
                    
                    if (isDrawingMode) {
                        // 绘制模式下，强制添加点
                        console.log('[地图点击] 绘制模式，调用addDrawPoint');
                        addDrawPoint(e.latlng);
                        L.DomEvent.stopPropagation(e);
                        return false;
                    } else if (isDrawingFieldMode) {
                        addFieldBoundaryPoint(e.latlng);
                    }
                });
                
                // 添加原生DOM点击监听器作为备用（优先级最高）
                const mapContainer = document.getElementById('gis-map');
                if (mapContainer) {
                    mapContainer.addEventListener('click', function(e) {
                        if (isDrawingMode) {
                            console.log('[DOM点击] 捕获到点击，isDrawingMode=true');
                            // 将屏幕坐标转换为地图坐标
                            const point = gisMap.mouseEventToLatLng(e);
                            console.log('[DOM点击] 转换坐标:', point);
                            addDrawPoint(point);
                            e.stopPropagation();
                            e.preventDefault();
                        }
                    }, true);  // true = 捕获阶段，最先触发
                }
                
                // 地图右键事件（撤销上一个点）
                gisMap.on('contextmenu', function(e) {
                    e.originalEvent.preventDefault();
                    if (isDrawingMode && drawingPoints.length > 0) {
                        undoLastPoint();
                    } else if (isDrawingFieldMode && fieldDrawingPoints.length > 0) {
                        undoLastFieldPoint();
                    }
                });
                
                // ESC键取消绘制
                document.addEventListener('keydown', function(e) {
                    if (e.key === 'Escape') {
                        if (isDrawingMode) {
                            cancelDrawing();
                        } else if (isDrawingFieldMode) {
                            cancelFieldDrawing();
                        }
                    }
                });
                
                // 定时更新GPS位置到GIS地图
                setInterval(updateGISGPS, 2000);
                
                console.log('[GIS] 地图初始化完成');
            } catch(e) {
                console.error('[GIS] 地图初始化失败:', e);
            }
        }
        
        // 更新GIS地图上的GPS位置
        function updateGISGPS() {
            if (!gisMap || !gisMarker) return;
            
            fetch('/api/gps').then(r => r.json()).then(data => {
                if (data.connected && data.latitude != 0) {
                    const pos = [data.latitude, data.longitude];
                    gisMarker.setLatLng(pos);
                    
                    // 添加到轨迹
                    gpsTrackPoints.push(pos);
                    if (gpsTrackPoints.length > 500) gpsTrackPoints.shift();
                    gpsTrackLine.setLatLngs(gpsTrackPoints);
                    
                    // 更新标记信息
                    gisMarker.bindPopup(`
                        GPS: ${data.satellites}颗卫星<br>
                        ${data.fix_type}<br>
                        位置: ${data.latitude.toFixed(6)}, ${data.longitude.toFixed(6)}
                    `);
                }
            }).catch(e => console.error('[GIS] GPS更新失败:', e));
        }
        
        // GIS地图控制函数
        function gisZoomIn() {
            if (gisMap) {
                gisMap.zoomIn();
                showToast('地图放大', 'info');
            }
        }
        
        function gisZoomOut() {
            if (gisMap) {
                gisMap.zoomOut();
                showToast('地图缩小', 'info');
            }
        }
        
        function gisResetView() {
            if (gisMap && gisMarker) {
                gisMap.setView(gisMarker.getLatLng(), 17);
                showToast('地图已重置到当前GPS位置', 'success');
            }
        }
        
        // 存储绘制的标记点
        let drawingMarkers = [];
        
        // 添加绘制点
        function addDrawPoint(latlng) {
            console.log(`[绘制] 尝试添加点:`, latlng, `当前模式: isDrawingMode=${isDrawingMode}`);
            
            if (!isDrawingMode) {
                console.log('[绘制] 警告：不在绘制模式，忽略');
                return;
            }
            
            drawingPoints.push(latlng);
            
            // 更新绘制线
            if (currentDrawing) {
                gisMap.removeLayer(currentDrawing);
            }
            
            currentDrawing = L.polyline(drawingPoints, {
                color: '#f39c12',
                weight: 4,
                opacity: 0.8,
                dashArray: '10, 10',
                interactive: false  // 不拦截点击
            }).addTo(gisMap);
            
            // 添加点标记
            const marker = L.circleMarker(latlng, {
                radius: 5,
                fillColor: '#f39c12',
                color: '#fff',
                weight: 2,
                fillOpacity: 1,
                interactive: false  // 不拦截点击
            }).addTo(gisMap).bindPopup(`点 ${drawingPoints.length}<br>${latlng.lat.toFixed(6)}, ${latlng.lng.toFixed(6)}`);
            
            drawingMarkers.push(marker);
            
            // 更新计数
            const countEl = document.getElementById('draw-count');
            if (countEl) countEl.textContent = drawingPoints.length;
            
            console.log(`[绘制] 成功添加点 ${drawingPoints.length}:`, latlng);
        }
        
        // 撤销上一个点
        function undoLastPoint() {
            if (drawingPoints.length === 0) return;
            
            // 移除最后一个点
            drawingPoints.pop();
            const lastMarker = drawingMarkers.pop();
            if (lastMarker) gisMap.removeLayer(lastMarker);
            
            // 更新绘制线
            if (currentDrawing) {
                gisMap.removeLayer(currentDrawing);
            }
            
            if (drawingPoints.length > 0) {
                currentDrawing = L.polyline(drawingPoints, {
                    color: '#f39c12',
                    weight: 4,
                    opacity: 0.8,
                    dashArray: '10, 10'
                }).addTo(gisMap);
            } else {
                currentDrawing = null;
            }
            
            // 更新计数
            const countEl = document.getElementById('draw-count');
            if (countEl) countEl.textContent = drawingPoints.length;
            
            showToast(`已撤销，剩余 ${drawingPoints.length} 个点`, 'info');
            console.log(`[撤销] 剩余点数: ${drawingPoints.length}`);
        }
        
        // 开始绘制模式
        function startDrawingMode(pathName) {
            isDrawingMode = true;
            drawingPoints = [];
            document.getElementById('draw-indicator').style.display = 'block';
            document.getElementById('draw-count').textContent = '0';
            showToast('绘制模式已启动，在地图上点击添加路径点', 'success');
        }
        
        // 代码版本标识（用于验证是否加载了最新代码）
        window.GIS_CODE_VERSION = '2025-10-24-00:31';
        console.log('%c[版本检查] GIS代码版本: ' + window.GIS_CODE_VERSION, 'color: green; font-weight: bold; font-size: 14px;');
        console.log('%c[版本检查] 如果看到此消息，说明已加载最新代码', 'color: green;');
        
        // 防止重复提交
        let isSavingPath = false;
        let saveCallCounter = 0;  // 调用计数器
        
        // 结束绘制并保存
        function finishDrawing() {
            saveCallCounter++;
            const callId = saveCallCounter;
            console.log(`[DEBUG-${callId}] ===== finishDrawing 被调用 (第${callId}次) =====`);
            console.log(`[DEBUG-${callId}] isSavingPath 当前值:`, isSavingPath);
            console.log(`[DEBUG-${callId}] 绘制点数:`, drawingPoints.length);
            
            if (drawingPoints.length < 2) {
                showToast('至少需要2个点才能保存路径', 'warning');
                console.log(`[DEBUG-${callId}] 点数不足，终止`);
                return;
            }
            
            // 防止重复提交
            if (isSavingPath) {
                console.warn(`[DEBUG-${callId}] 正在保存中，忽略重复调用！`);
                alert('正在保存中，请勿重复点击！');
                return;
            }
            isSavingPath = true;
            console.log(`[DEBUG-${callId}] 设置 isSavingPath = true，开始保存流程`);
            
            // 使用临时保存的路径信息
            const pathInfo = window.tempPathInfo || {};
            const pathName = pathInfo.name || `路径_${Date.now()}`;
            const pathType = pathInfo.type || '手动绘制';
            const fieldId = pathInfo.fieldId || currentDrawingFieldId;
            
            console.log(`[DEBUG-${callId}] 读取路径信息:`, pathInfo);
            console.log(`[DEBUG-${callId}] 最终路径名称: ${pathName}`);
            
            isDrawingMode = false;
            const indicator = document.getElementById('draw-indicator');
            if (indicator) indicator.style.display = 'none';
            
            // 清除临时绘制线
            if (currentDrawing) {
                gisMap.removeLayer(currentDrawing);
            }
            
            // 清除临时标记点（橙色）
            drawingMarkers.forEach(m => gisMap.removeLayer(m));
            drawingMarkers = [];
            
            // 创建最终路径（绿色）
            // 使用时间戳生成唯一ID，避免重复
            const timestamp = Date.now();
            const pathId = 'PATH-' + timestamp;
            
            const finalPath = L.polyline(drawingPoints, {
                color: '#27ae60',
                weight: 3,
                opacity: 0.9
            }).addTo(gisMap);
            
            finalPath.bindPopup(`
                <strong>${pathName || pathId}</strong><br>
                点位数: ${drawingPoints.length}<br>
                长度: ${calculatePathLength(drawingPoints).toFixed(1)}m
            `);
            
            // 在路径点上添加永久标记（绿色）
            drawingPoints.forEach((p, i) => {
                L.circleMarker(p, {
                    radius: 4,
                    fillColor: '#27ae60',
                    color: '#fff',
                    weight: 2,
                    fillOpacity: 0.8
                }).addTo(gisMap).bindPopup(`${pathName}<br>点 ${i+1}/${drawingPoints.length}`);
            });
            
            // 保存路径数据
            const pathLength = calculatePathLength(drawingPoints);
            const pathData = {
                id: pathId,
                name: pathName || pathId,
                type: pathType || '手动绘制',
                points: drawingPoints.map(p => [p.lat, p.lng]),
                created: new Date().toISOString(),
                status: '待验证',
                point_count: drawingPoints.length,
                length: parseFloat(pathLength.toFixed(1)),
                field_id: fieldId  // 关联到地块
            };
            
            // 保存到pathLayers
            pathLayers[pathId] = finalPath;
            visiblePaths.add(pathId);
            
            console.log(`[DEBUG-${callId}] 路径数据准备完成:`, pathData);
            
            // 确定保存的地图ID
            const targetMapId = currentMapId || 'MAP-001';
            console.log(`[DEBUG-${callId}] 目标地图: ${targetMapId}`);
            
            // 保存到服务器
            console.log(`[DEBUG-${callId}] 开始发送保存请求...`);
            fetch(`/api/gis/map/${targetMapId}/save_path`, {
                method: 'POST',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify(pathData)
            }).then(r => r.json()).then(result => {
                console.log(`[DEBUG-${callId}] 服务器响应:`, result);
                
                if (result.success) {
                    if (result.duplicated) {
                        console.warn(`[DEBUG-${callId}] 路径ID已存在，服务器已跳过保存`);
                        showToast('路径ID已存在，未重复保存', 'info');
                    } else {
                        console.log(`[DEBUG-${callId}] 路径成功保存到${targetMapId}`);
                        
                        // 如果有关联地块，更新地块的paths数组
                        if (fieldId) {
                            console.log(`[DEBUG-${callId}] 关联路径${pathId}到地块${fieldId}`);
                            updateFieldPaths(fieldId, pathId);
                        }
                        
                        showToast(`路径已保存: ${pathName} (${drawingPoints.length}点, ${pathLength.toFixed(1)}m)`, 'success');
                        
                        // 设置当前地图ID（如果还没设置）
                        if (!currentMapId) {
                            currentMapId = targetMapId;
                            console.log(`[DEBUG-${callId}] 设置当前地图为: ${currentMapId}`);
                        }
                        
                        // 刷新左侧路径列表
                        console.log(`[DEBUG-${callId}] 准备刷新路径列表...`);
                        refreshGISPanel();
                    }
                } else {
                    console.error(`[DEBUG-${callId}] 保存失败:`, result.error);
                    showToast('路径保存失败', 'danger');
                }
            }).catch(e => {
                console.error(`[DEBUG-${callId}] 保存请求失败:`, e);
                showToast('路径已在地图上显示，服务器保存失败', 'warning');
            }).finally(() => {
                console.log(`[DEBUG-${callId}] 保存流程完成，准备重置标志`);
            });
            
            // 恢复所有地块图层的交互和popup
            restoreFieldInteraction();
            
            // 清理绘制状态
            drawingPoints = [];
            currentDrawing = null;
            currentDrawingFieldId = null;
            window.tempPathInfo = null;
            
            // 重置保存标志（延迟重置，避免重复点击）
            setTimeout(() => {
                isSavingPath = false;
                console.log(`[DEBUG-${callId}] 保存标志已重置 (2秒后)`);
            }, 3000);  // 延长到3秒
            
            console.log(`[DEBUG-${callId}] 已恢复地块交互，finishDrawing 执行完毕`);
            console.log(`[DEBUG-${callId}] ===== finishDrawing 结束 =====`);
        }
        
        // 刷新左侧路径列表
        function refreshGISPanel() {
            const mapId = currentMapId || 'MAP-001';  // 如果没有选择地图，使用默认地图
            console.log(`[刷新] 刷新路径列表，地图: ${mapId}`);
            
            fetch(`/api/gis/map/${mapId}/paths`)
                .then(r => r.json())
                .then(data => {
                    const paths = data.paths || [];
                    console.log(`[刷新] 获取到${paths.length}条路径`);
                    
                    const pathListHtml = paths.map((path, i) => {
                        const colors = ['#3498db', '#27ae60', '#f39c12'];
                        const color = colors[i % 3];
                        const statusBadge = path.status === '已验证' ? 
                            '<span class="badge badge-success" style="font-size: 10px;">已验证</span>' :
                            '<span class="badge badge-warning" style="font-size: 10px;">待验证</span>';
                        
                        // 转义特殊字符，防止在HTML属性中出错
                        const safePathId = path.id.replace(/'/g, "\\'");
                        const safePathName = path.name.replace(/'/g, "\\'");
                        
                        return `
                            <div style="background: #f8f9fa; padding: 10px; border-radius: 4px; margin-bottom: 6px; border-left: 3px solid ${color}; position: relative;" data-path-id="${path.id}">
                                <div style="cursor: pointer;" onclick="loadPathById('${safePathId}')">
                                    <div style="font-weight: 600; color: #2c3e50; font-size: 13px; margin-bottom: 3px;">${path.name}</div>
                                    <div style="font-size: 11px; color: #7f8c8d;">ID: ${path.id} | ${path.point_count}点 | ${path.length}m</div>
                                    <div style="margin-top: 5px;">${statusBadge}</div>
                                </div>
                                <button class="delete-path-btn" data-path-id="${path.id}" data-path-name="${path.name}" style="position: absolute; top: 8px; right: 8px; background: #e74c3c; color: white; border: none; border-radius: 3px; padding: 4px 8px; font-size: 11px; cursor: pointer;">删除</button>
                            </div>
                        `;
                    }).join('');
                    
                    // 更新列表容器
                    const listContainer = document.getElementById('gis-path-list');
                    const countEl = document.getElementById('gis-path-count');
                    
                    if (listContainer) {
                        listContainer.innerHTML = pathListHtml || '<div style="color: #7f8c8d; padding: 15px; text-align: center; font-size: 12px;">暂无路径</div>';
                        console.log('[刷新] 路径列表HTML已更新');
                        
                        // 为删除按钮绑定事件（使用事件委托）
                        const deleteButtons = listContainer.querySelectorAll('.delete-path-btn');
                        deleteButtons.forEach(btn => {
                            btn.addEventListener('click', function(e) {
                                e.stopPropagation();  // 阻止事件冒泡
                                const pathId = this.getAttribute('data-path-id');
                                const pathName = this.getAttribute('data-path-name');
                                deletePathConfirm(pathId, pathName);
                            });
                        });
                    } else {
                        console.error('[刷新] 找不到gis-path-list容器');
                    }
                    
                    if (countEl) {
                        countEl.textContent = paths.length;
                        console.log(`[刷新] 路径计数已更新: ${paths.length}`);
                    } else {
                        console.error('[刷新] 找不到gis-path-count元素');
                    }
                    
                    console.log(`[刷新] 列表刷新完成: ${paths.length} 条路径`);
                })
                .catch(e => console.error('[刷新] 刷新列表失败:', e));
        }
        
        // 通过ID加载路径
        // 删除路径确认
        function deletePathConfirm(pathId, pathName) {
            if (confirm(`确定要删除路径 "${pathName}" 吗？\n\n此操作不可恢复！`)) {
                deletePath(pathId);
            }
        }
        
        // 删除路径
        function deletePath(pathId) {
            const mapId = currentMapId || 'MAP-001';
            console.log(`[删除] 删除路径: ${pathId} from ${mapId}`);
            
            fetch(`/api/gis/map/${mapId}/delete_path/${pathId}`, {
                method: 'DELETE'
            })
            .then(r => r.json())
            .then(result => {
                if (result.success) {
                    showToast('路径已删除', 'success');
                    
                    // 从地图上移除
                    const layer = pathLayers[pathId];
                    if (layer && gisMap) {
                        gisMap.removeLayer(layer);
                        delete pathLayers[pathId];
                    }
                    visiblePaths.delete(pathId);
                    
                    // 刷新列表
                    refreshGISPanel();
                    console.log(`[删除] 路径 ${pathId} 已删除`);
                } else {
                    showToast('删除失败', 'danger');
                    console.error('[删除] 删除失败:', result.error);
                }
            })
            .catch(e => {
                console.error('[删除] 删除请求失败:', e);
                showToast('删除请求失败', 'danger');
            });
        }
        
        function loadPathById(pathId) {
            if (!currentMapData || !currentMapData.paths) return;
            
            const path = currentMapData.paths.find(p => p.id === pathId);
            if (path && gisMap) {
                // 定位到路径
                const bounds = L.latLngBounds(path.points);
                gisMap.fitBounds(bounds, { padding: [50, 50] });
                
                // 高亮显示
                const layer = pathLayers[pathId];
                if (layer) {
                    layer.setStyle({ weight: 5, opacity: 1 });
                    layer.openPopup();
                    
                    setTimeout(() => {
                        layer.setStyle({ weight: 3, opacity: 0.8 });
                    }, 3000);
                }
                
                showToast(`已定位到: ${path.name}`, 'success');
            }
        }
        
        // 地块绘制相关变量
        let isDrawingFieldMode = false;
        let fieldDrawingPoints = [];
        let currentFieldDrawing = null;
        let fieldDrawingMarkers = [];
        let newFieldInfo = {};
        
        // 新建地块
        function createNewField() {
            const html = `
                <div style="background: #f8f9fa; padding: 20px; border-radius: 6px; margin-bottom: 20px;">
                    <div style="font-weight: 600; color: #2c3e50; margin-bottom: 15px;">新建地块</div>
                    
                    <div style="margin-bottom: 15px;">
                        <label style="display: block; color: #7f8c8d; margin-bottom: 8px; font-size: 13px;">地块名称</label>
                        <input type="text" id="new-field-name" placeholder="例如：北区甘蔗地D" style="width: 100%; padding: 10px; border: 1px solid #bdc3c7; border-radius: 4px;">
                    </div>
                    
                    <div style="margin-bottom: 15px;">
                        <label style="display: block; color: #7f8c8d; margin-bottom: 8px; font-size: 13px;">作物类型</label>
                        <select id="new-field-crop" style="width: 100%; padding: 10px; border: 1px solid #bdc3c7; border-radius: 4px; background: white; color: #2c3e50;">
                            <option>甘蔗</option>
                            <option>玉米</option>
                            <option>水稻</option>
                        </select>
                    </div>
                    
                    <div style="margin-bottom: 20px;">
                        <label style="display: block; color: #7f8c8d; margin-bottom: 8px; font-size: 13px;">种植日期</label>
                        <input type="date" id="new-field-date" value="2024-10-23" style="width: 100%; padding: 10px; border: 1px solid #bdc3c7; border-radius: 4px;">
                    </div>
                </div>
                
                <div style="background: #e3f2fd; padding: 15px; border-radius: 6px; border-left: 4px solid #3498db; margin-bottom: 15px;">
                    <div style="font-weight: 600; color: #2c3e50; margin-bottom: 8px;">创建方式</div>
                    <div style="color: #2c3e50; font-size: 13px; line-height: 1.8;">
                        <strong>绘制边界：</strong>在地图上点击设置地块边界点（至少3个点）<br>
                        <strong>自动计算：</strong>系统自动计算中心点和面积
                    </div>
                </div>
                
                <div class="modal-buttons">
                    <button class="modal-btn btn-success" onclick="startDrawFieldBoundary()">在地图上绘制边界</button>
                    <button class="modal-btn btn-default" onclick="closeModal()">取消</button>
                </div>
            `;
            
            showModal('新建地块', html);
        }
        
        // 开始绘制地块边界
        function startDrawFieldBoundary() {
            const name = document.getElementById('new-field-name').value;
            const crop = document.getElementById('new-field-crop').value;
            const date = document.getElementById('new-field-date').value;
            
            if (!name) {
                showToast('请先输入地块名称', 'warning');
                return;
            }
            
            // 保存地块信息
            newFieldInfo = { name, crop, date };
            
            // 关闭弹窗
            closeModal();
            
            // 启动地块边界绘制模式
            isDrawingFieldMode = true;
            fieldDrawingPoints = [];
            
            // 显示绘制控制条
            const indicator = document.getElementById('draw-indicator');
            if (indicator) {
                indicator.innerHTML = `
                    <div style="display: flex; align-items: center; justify-content: space-between; gap: 20px;">
                        <div style="flex: 1;">
                            <div style="font-weight: 600; color: white; font-size: 14px; margin-bottom: 5px;">
                                绘制地块边界：${name}
                            </div>
                            <div style="color: rgba(255,255,255,0.9); font-size: 12px;">
                                点击地图设置边界点 | 右键撤销 | ESC取消
                            </div>
                        </div>
                        <div style="display: flex; align-items: center; gap: 15px;">
                            <div style="text-align: center;">
                                <div style="color: rgba(255,255,255,0.8); font-size: 11px;">已添加</div>
                                <div style="color: white; font-size: 24px; font-weight: 700;" id="field-draw-count">0</div>
                                <div style="color: rgba(255,255,255,0.7); font-size: 10px;">个点</div>
                            </div>
                            <div style="display: flex; gap: 8px;">
                                <button style="padding: 10px 20px; background: #27ae60; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 13px; font-weight: 600;" onclick="finishFieldDrawing()">完成</button>
                                <button style="padding: 10px 20px; background: #e74c3c; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 13px; font-weight: 600;" onclick="cancelFieldDrawing()">取消</button>
                            </div>
                        </div>
                    </div>
                `;
                indicator.style.display = 'block';
                indicator.style.background = '#9b59b6';
                indicator.style.borderColor = '#9b59b6';
            }
            
            showToast('地块边界绘制模式已启动，在地图上点击设置边界点（至少3个点）', 'success');
        }
        
        // 添加地块边界点
        function addFieldBoundaryPoint(latlng) {
            fieldDrawingPoints.push(latlng);
            
            // 移除旧的绘制层
            if (currentFieldDrawing) {
                gisMap.removeLayer(currentFieldDrawing);
            }
            
            // 绘制多边形（紫色半透明）
            currentFieldDrawing = L.polygon(fieldDrawingPoints, {
                color: '#9b59b6',
                weight: 3,
                fillColor: '#9b59b6',
                fillOpacity: 0.2,
                dashArray: '8, 8'
            }).addTo(gisMap);
            
            // 添加点标记
            const marker = L.circleMarker(latlng, {
                radius: 5,
                fillColor: '#9b59b6',
                color: '#fff',
                weight: 2,
                fillOpacity: 1
            }).addTo(gisMap).bindPopup(`边界点 ${fieldDrawingPoints.length}<br>${latlng.lat.toFixed(6)}, ${latlng.lng.toFixed(6)}`);
            
            fieldDrawingMarkers.push(marker);
            
            // 更新计数
            const countEl = document.getElementById('field-draw-count');
            if (countEl) countEl.textContent = fieldDrawingPoints.length;
            
            console.log(`[地块绘制] 添加边界点 ${fieldDrawingPoints.length}:`, latlng);
        }
        
        // 撤销最后一个边界点
        function undoLastFieldPoint() {
            if (fieldDrawingPoints.length === 0) return;
            
            fieldDrawingPoints.pop();
            const lastMarker = fieldDrawingMarkers.pop();
            if (lastMarker) gisMap.removeLayer(lastMarker);
            
            if (currentFieldDrawing) {
                gisMap.removeLayer(currentFieldDrawing);
            }
            
            if (fieldDrawingPoints.length > 0) {
                currentFieldDrawing = L.polygon(fieldDrawingPoints, {
                    color: '#9b59b6',
                    weight: 3,
                    fillColor: '#9b59b6',
                    fillOpacity: 0.2,
                    dashArray: '8, 8'
                }).addTo(gisMap);
            } else {
                currentFieldDrawing = null;
            }
            
            const countEl = document.getElementById('field-draw-count');
            if (countEl) countEl.textContent = fieldDrawingPoints.length;
            
            showToast(`已撤销，剩余 ${fieldDrawingPoints.length} 个点`, 'info');
        }
        
        // 完成地块边界绘制
        function finishFieldDrawing() {
            if (fieldDrawingPoints.length < 3) {
                showToast('至少需要3个点才能形成地块边界', 'warning');
                return;
            }
            
            // 计算中心点
            let sumLat = 0, sumLng = 0;
            fieldDrawingPoints.forEach(p => {
                sumLat += p.lat;
                sumLng += p.lng;
            });
            const center = [sumLat / fieldDrawingPoints.length, sumLng / fieldDrawingPoints.length];
            
            // 计算面积（简化算法，基于凸多边形）
            let area = 0;
            for (let i = 0; i < fieldDrawingPoints.length; i++) {
                const j = (i + 1) % fieldDrawingPoints.length;
                area += fieldDrawingPoints[i].lat * fieldDrawingPoints[j].lng;
                area -= fieldDrawingPoints[j].lat * fieldDrawingPoints[i].lng;
            }
            area = Math.abs(area / 2) * 111000 * 111000 / 666.667; // 转换为亩（粗略）
            
            // 清除临时绘制
            if (currentFieldDrawing) gisMap.removeLayer(currentFieldDrawing);
            fieldDrawingMarkers.forEach(m => gisMap.removeLayer(m));
            
            // 准备地块数据
            const fieldData = {
                name: newFieldInfo.name,
                area: parseFloat(area.toFixed(1)),
                center: center,
                boundary: fieldDrawingPoints.map(p => [p.lat, p.lng]),
                crop_type: newFieldInfo.crop,
                planting_date: newFieldInfo.date,
                last_work: null
            };
            
            // 保存到后端
            fetch('/api/gis/create_field', {
                method: 'POST',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify(fieldData)
            }).then(r => r.json()).then(result => {
                if (result.success) {
                    showToast(`地块创建成功: ${result.field_id}，面积 ${fieldData.area} 亩`, 'success');
                    
                    // 重置绘制状态
                    isDrawingFieldMode = false;
                    fieldDrawingPoints = [];
                    currentFieldDrawing = null;
                    fieldDrawingMarkers = [];
                    
                    // 隐藏控制条
                    const indicator = document.getElementById('draw-indicator');
                    if (indicator) {
                        indicator.style.display = 'none';
                        indicator.style.background = '#27ae60';
                        indicator.style.borderColor = '#27ae60';
                    }
                    
                    // 刷新地块列表和地图
                    loadFieldsData();
                } else {
                    showToast('创建失败: ' + result.error, 'danger');
                }
            }).catch(e => {
                console.error('[GIS] 创建地块失败:', e);
                showToast('创建失败', 'danger');
            });
        }
        
        // 取消地块边界绘制
        function cancelFieldDrawing() {
            isDrawingFieldMode = false;
            fieldDrawingPoints = [];
            
            if (currentFieldDrawing && gisMap) {
                gisMap.removeLayer(currentFieldDrawing);
                currentFieldDrawing = null;
            }
            
            fieldDrawingMarkers.forEach(m => {
                if (gisMap) gisMap.removeLayer(m);
            });
            fieldDrawingMarkers = [];
            
            const indicator = document.getElementById('draw-indicator');
            if (indicator) {
                indicator.style.display = 'none';
                indicator.style.background = '#27ae60';
                indicator.style.borderColor = '#27ae60';
            }
            
            showToast('已取消地块边界绘制', 'info');
        }
        
        function useCurrentGPS() {
            fetch('/api/gps').then(r => r.json()).then(data => {
                if (data.connected && data.latitude != 0) {
                    document.getElementById('new-field-lat').value = data.latitude.toFixed(5);
                    document.getElementById('new-field-lng').value = data.longitude.toFixed(5);
                    showToast('已使用当前GPS坐标', 'success');
                } else {
                    showToast('GPS未定位', 'warning');
                }
            });
        }
        
        // 刷新所有GIS数据
        function refreshAllGISData() {
            showToast('正在刷新数据...', 'info');
            console.log('[刷新] 刷新所有GIS数据');
            
            // 重新加载地块
            loadFieldsData();
            
            // 重新加载当前地图的路径（如果没有选择地图，默认使用MAP-001）
            const mapId = currentMapId || 'MAP-001';
            console.log(`[刷新] 刷新地图 ${mapId} 的路径数据`);
            
            fetch(`/api/gis/map/${mapId}/paths`)
                .then(r => r.json())
                .then(data => {
                    currentMapData = data;
                    if (!currentMapId) {
                        currentMapId = mapId;  // 设置默认地图
                    }
                    refreshGISPanel();
                    showToast('数据刷新完成', 'success');
                    console.log(`[刷新] 路径数据刷新完成，共${data.paths?.length || 0}条`);
                })
                .catch(e => {
                    console.error('[刷新] 刷新失败:', e);
                    showToast('刷新失败', 'danger');
                });
        }
        
        // 编辑地块
        function editFieldModal(fieldId) {
            fetch(`/api/gis/field/${fieldId}`)
                .then(r => r.json())
                .then(field => {
                    if (field.error) {
                        showToast('地块数据未找到', 'warning');
                        return;
                    }
                    
                    const boundaryHtml = (field.boundary || []).map((point, i) => `
                        <tr>
                            <td style="padding: 8px; text-align: center; color: #7f8c8d; font-size: 12px;">点 ${i+1}</td>
                            <td style="padding: 8px;">
                                <input type="number" id="boundary-lat-${i}" value="${point[0].toFixed(5)}" step="0.00001" style="width: 100%; padding: 6px; border: 1px solid #bdc3c7; border-radius: 3px; font-size: 12px;">
                            </td>
                            <td style="padding: 8px;">
                                <input type="number" id="boundary-lng-${i}" value="${point[1].toFixed(5)}" step="0.00001" style="width: 100%; padding: 6px; border: 1px solid #bdc3c7; border-radius: 3px; font-size: 12px;">
                            </td>
                        </tr>
                    `).join('');
                    
                    const html = `
                        <div style="background: #f8f9fa; padding: 20px; border-radius: 6px; margin-bottom: 20px;">
                            <div style="font-weight: 600; color: #2c3e50; margin-bottom: 15px;">编辑地块信息</div>
                            
                            <div style="margin-bottom: 15px;">
                                <label style="display: block; color: #7f8c8d; margin-bottom: 8px; font-size: 13px;">地块编号</label>
                                <input type="text" value="${field.id}" disabled style="width: 100%; padding: 10px; border: 1px solid #bdc3c7; border-radius: 4px; background: #ecf0f1; color: #7f8c8d;">
                            </div>
                            
                            <div style="margin-bottom: 15px;">
                                <label style="display: block; color: #7f8c8d; margin-bottom: 8px; font-size: 13px;">地块名称</label>
                                <input type="text" id="edit-field-name" value="${field.name}" style="width: 100%; padding: 10px; border: 1px solid #bdc3c7; border-radius: 4px;">
                            </div>
                            
                            <div style="margin-bottom: 15px;">
                                <label style="display: block; color: #7f8c8d; margin-bottom: 8px; font-size: 13px;">地块面积（亩）</label>
                                <input type="number" id="edit-field-area" value="${field.area}" min="1" step="0.1" style="width: 100%; padding: 10px; border: 1px solid #bdc3c7; border-radius: 4px;">
                            </div>
                            
                            <div style="margin-bottom: 15px;">
                                <label style="display: block; color: #7f8c8d; margin-bottom: 8px; font-size: 13px;">作物类型</label>
                                <input type="text" id="edit-field-crop" value="${field.crop_type || '甘蔗'}" style="width: 100%; padding: 10px; border: 1px solid #bdc3c7; border-radius: 4px;">
                            </div>
                            
                            <div style="margin-bottom: 15px;">
                                <label style="display: block; color: #7f8c8d; margin-bottom: 8px; font-size: 13px;">种植日期</label>
                                <input type="date" id="edit-field-date" value="${field.planting_date || ''}" style="width: 100%; padding: 10px; border: 1px solid #bdc3c7; border-radius: 4px;">
                            </div>
                            
                            <div>
                                <label style="display: block; color: #7f8c8d; margin-bottom: 8px; font-size: 13px;">边界坐标（精细调整）</label>
                                <div style="max-height: 200px; overflow-y: auto; background: white; border: 1px solid #bdc3c7; border-radius: 4px; padding: 8px;">
                                    <table style="width: 100%; border-collapse: collapse;">
                                        <thead>
                                            <tr style="background: #f8f9fa;">
                                                <th style="padding: 8px; text-align: center; color: #7f8c8d; font-size: 12px;">序号</th>
                                                <th style="padding: 8px; text-align: center; color: #7f8c8d; font-size: 12px;">纬度</th>
                                                <th style="padding: 8px; text-align: center; color: #7f8c8d; font-size: 12px;">经度</th>
                                            </tr>
                                        </thead>
                                        <tbody id="boundary-points-table">
                                            ${boundaryHtml}
                                        </tbody>
                                    </table>
                                </div>
                            </div>
                        </div>
                        
                        <div class="modal-buttons">
                            <button class="modal-btn btn-success" onclick="confirmEditField('${field.id}', ${field.boundary ? field.boundary.length : 0})">保存修改</button>
                            <button class="modal-btn btn-default" onclick="closeModal()">取消</button>
                        </div>
                    `;
                    
                    showModal('编辑地块', html);
                });
        }
        
        function confirmEditField(fieldId, boundaryCount) {
            // 读取修改后的边界坐标
            const newBoundary = [];
            for (let i = 0; i < boundaryCount; i++) {
                const latEl = document.getElementById(`boundary-lat-${i}`);
                const lngEl = document.getElementById(`boundary-lng-${i}`);
                if (latEl && lngEl) {
                    newBoundary.push([parseFloat(latEl.value), parseFloat(lngEl.value)]);
                }
            }
            
            // 计算新的中心点
            let sumLat = 0, sumLng = 0;
            newBoundary.forEach(p => {
                sumLat += p[0];
                sumLng += p[1];
            });
            const newCenter = newBoundary.length > 0 ? 
                [sumLat / newBoundary.length, sumLng / newBoundary.length] : null;
            
            const updates = {
                name: document.getElementById('edit-field-name').value,
                area: parseFloat(document.getElementById('edit-field-area').value),
                crop_type: document.getElementById('edit-field-crop').value,
                planting_date: document.getElementById('edit-field-date').value,
                boundary: newBoundary,
                center: newCenter
            };
            
            fetch(`/api/gis/field/${fieldId}/update`, {
                method: 'POST',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify(updates)
            }).then(r => r.json()).then(result => {
                if (result.success) {
                    closeModal();
                    showToast('地块信息已更新', 'success');
                    
                    // 清除旧图层
                    const layer = fieldLayers[fieldId];
                    if (layer && gisMap) {
                        gisMap.removeLayer(layer);
                        delete fieldLayers[fieldId];
                    }
                    
                    // 重新加载地块
                    loadFieldsData();
                } else {
                    showToast('更新失败', 'danger');
                }
            }).catch(e => {
                console.error('[GIS] 更新地块失败:', e);
                showToast('更新失败', 'danger');
            });
        }
        
        // 查看地块详情
        function viewFieldDetail(fieldId) {
            fetch(`/api/gis/field/${fieldId}`)
                .then(r => r.json())
                .then(field => {
                    if (field.error) {
                        showToast('地块数据未找到', 'warning');
                        return;
                    }
                    
                    // 定位到地块
                    if (gisMap && field.center) {
                        gisMap.setView(field.center, 16);
                        
                        const layer = fieldLayers[fieldId];
                        if (layer) {
                            layer.setStyle({ weight: 4, fillOpacity: 0.3 });
                            layer.openPopup();
                            setTimeout(() => {
                                layer.setStyle({ weight: 2, fillOpacity: 0.15 });
                            }, 3000);
                        }
                    }
                    
                    showFieldDetailModal(field);
                });
        }
        
        function showFieldDetailModal(field) {
            const coord = `${field.center[1].toFixed(5)}, ${field.center[0].toFixed(5)}`;
            const pathCount = field.paths ? field.paths.length : 0;
            
            const html = `
                <div style="background: #f8f9fa; padding: 20px; border-radius: 8px; margin-bottom: 20px;">
                    <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
                        <div>
                            <div style="color: #27ae60; font-size: 24px; font-weight: 700;">${field.id}</div>
                            <div style="color: #2c3e50; font-size: 16px; margin-top: 5px;">${field.name}</div>
                        </div>
                        <div style="text-align: right;">
                            <div style="color: #7f8c8d; font-size: 12px;">地块面积</div>
                            <div style="color: #f39c12; font-size: 28px; font-weight: 700;">${field.area} <span style="font-size: 14px;">亩</span></div>
                        </div>
                    </div>
                    
                    <table style="width: 100%; border-collapse: collapse;">
                        <tr style="border-bottom: 1px solid #ecf0f1;">
                            <td style="padding: 10px; color: #7f8c8d; width: 120px;">中心坐标</td>
                            <td style="padding: 10px; font-family: monospace; color: #3498db; font-weight: 600;">${coord}</td>
                        </tr>
                        <tr style="border-bottom: 1px solid #ecf0f1;">
                            <td style="padding: 10px; color: #7f8c8d;">作业进度</td>
                            <td style="padding: 10px;">
                                <div style="display: flex; align-items: center; gap: 10px;">
                                    <div style="flex: 1; background: #ecf0f1; height: 6px; border-radius: 3px; overflow: hidden;">
                                        <div style="background: ${field.progress === 100 ? '#27ae60' : '#3498db'}; height: 100%; width: ${field.progress}%;"></div>
                                    </div>
                                    <span style="color: ${field.progress === 100 ? '#27ae60' : '#3498db'}; font-weight: 600;">${field.progress}%</span>
                                </div>
                            </td>
                        </tr>
                        <tr style="border-bottom: 1px solid #ecf0f1;">
                            <td style="padding: 10px; color: #7f8c8d;">关联路径</td>
                            <td style="padding: 10px; color: #3498db; font-weight: 600;">${pathCount} 条</td>
                        </tr>
                        <tr style="border-bottom: 1px solid #ecf0f1;">
                            <td style="padding: 10px; color: #7f8c8d;">作物类型</td>
                            <td style="padding: 10px; color: #2c3e50;">${field.crop_type || '甘蔗'}</td>
                        </tr>
                        <tr style="border-bottom: 1px solid #ecf0f1;">
                            <td style="padding: 10px; color: #7f8c8d;">种植日期</td>
                            <td style="padding: 10px; color: #2c3e50;">${field.planting_date || '未设置'}</td>
                        </tr>
                        <tr>
                            <td style="padding: 10px; color: #7f8c8d;">上次作业</td>
                            <td style="padding: 10px; color: #2c3e50; font-weight: 600;">${field.last_work || '未开始'}</td>
                        </tr>
                    </table>
                </div>
                
                <div style="background: #e8f5e9; padding: 15px; border-radius: 6px; border-left: 4px solid #27ae60;">
                    <div style="font-weight: 600; color: #27ae60; margin-bottom: 8px;">作业统计</div>
                    <div style="color: #2c3e50; font-size: 13px; line-height: 2;">
                        已完成: <span style="font-weight: 600;">${(field.area * field.progress / 100).toFixed(1)} 亩</span><br>
                        剩余: <span style="font-weight: 600;">${(field.area * (100 - field.progress) / 100).toFixed(1)} 亩</span><br>
                        预计时间: <span style="font-weight: 600;">${field.progress === 100 ? '已完成' : Math.round((100 - field.progress) * field.area / 3.8 * 60) + ' 分钟'}</span>
                    </div>
                </div>
                
                <div class="modal-buttons">
                    <button class="modal-btn btn-primary" onclick="closeModal()">关闭</button>
                </div>
            `;
            
            showModal('地块详情', html);
        }
        
        // 删除地块
        function deleteFieldFromMap(fieldId) {
            if (!confirm(`确定删除地块 ${fieldId} 吗？此操作不可恢复。`)) {
                return;
            }
            
            fetch(`/api/gis/field/${fieldId}`, { method: 'DELETE' })
                .then(r => r.json())
                .then(result => {
                    if (result.success) {
                        const layer = fieldLayers[fieldId];
                        if (layer && gisMap) {
                            gisMap.removeLayer(layer);
                            delete fieldLayers[fieldId];
                        }
                        
                        loadFieldsData();
                        showToast(`地块 ${fieldId} 已删除`, 'success');
                    } else {
                        showToast('删除失败', 'danger');
                    }
                })
                .catch(e => {
                    console.error('[GIS] 删除地块失败:', e);
                    showToast('删除失败', 'danger');
                });
        }
        
        // 为指定地块绘制路径
        let currentDrawingFieldId = null;
        function drawPathForField(fieldId) {
            // 获取地块信息
            fetch(`/api/gis/field/${fieldId}`)
                .then(r => r.json())
                .then(field => {
                    if (field.error) {
                        showToast('地块数据未找到', 'warning');
                        return;
                    }
                    
                    currentDrawingFieldId = fieldId;
                    
                    // 聚焦到该地块
                    if (field.boundary && field.boundary.length > 0) {
                        const bounds = L.latLngBounds(field.boundary);
                        gisMap.fitBounds(bounds, { padding: [50, 50] });
                    }
                    
                    // 高亮显示该地块
                    highlightField(fieldId);
                    
                    // 弹出绘制路径的弹窗
                    showDrawPathDialog(field);
                })
                .catch(e => {
                    console.error('[GIS] 获取地块失败:', e);
                    showToast('获取地块信息失败', 'danger');
                });
        }
        
        // 显示绘制路径对话框
        function showDrawPathDialog(field) {
            const html = `
                <div style="background: #f8f9fa; padding: 20px; border-radius: 6px; margin-bottom: 20px;">
                    <div style="font-weight: 600; color: #2c3e50; margin-bottom: 15px;">为地块绘制作业路径</div>
                    
                    <div style="background: #e3f2fd; padding: 12px; border-radius: 4px; margin-bottom: 15px; border-left: 3px solid #3498db;">
                        <div style="font-weight: 600; color: #2c3e50; margin-bottom: 5px;">${field.name}</div>
                        <div style="font-size: 12px; color: #7f8c8d;">编号: ${field.id} | 面积: ${field.area}亩 | 已有路径: ${(field.paths && field.paths.length) || 0}条</div>
                    </div>
                    
                    <div style="margin-bottom: 15px;">
                        <label style="display: block; color: #7f8c8d; margin-bottom: 8px; font-size: 13px;">路径名称</label>
                        <input type="text" id="field-path-name" placeholder="例如：东区A地1号作业线" style="width: 100%; padding: 10px; border: 1px solid #bdc3c7; border-radius: 4px;">
                    </div>
                    
                    <div style="margin-bottom: 15px;">
                        <label style="display: block; color: #7f8c8d; margin-bottom: 8px; font-size: 13px;">路径类型</label>
                        <select id="field-path-type" style="width: 100%; padding: 10px; border: 1px solid #bdc3c7; border-radius: 4px; background: white;">
                            <option>直线型</option>
                            <option>曲线型</option>
                            <option>U型</option>
                            <option>往返型</option>
                            <option>螺旋型</option>
                        </select>
                    </div>
                    
                    <div style="background: #f8f9fa; padding: 12px; border-radius: 4px; margin-bottom: 15px; border-left: 3px solid #3498db;">
                        <div style="font-size: 12px; color: #2c3e50; line-height: 1.6;">
                            <strong>绘制方式：</strong><br>
                            手动绘制：在地图上点击添加路径点<br>
                            GPS记录：机器人行走时实时记录GPS轨迹<br>
                            AI规划：系统自动生成最优路径
                        </div>
                    </div>
                    
                    <div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px;">
                        <button class="btn btn-success" onclick="startManualDraw('${field.id}')" style="padding: 12px; font-weight: 600;">手动绘制</button>
                        <button class="btn btn-primary" onclick="startGPSRecordForField('${field.id}')" style="padding: 12px; font-weight: 600;">GPS记录</button>
                        <button class="btn btn-warning" onclick="startAIPlanningForField('${field.id}')" style="padding: 12px; font-weight: 600;">AI规划</button>
                    </div>
                </div>
                
                <div class="modal-buttons">
                    <button class="modal-btn btn-default" onclick="closeModal()">取消</button>
                </div>
            `;
            
            showModal('绘制作业路径', html);
        }
        
        // 高亮显示地块
        function highlightField(fieldId) {
            // 清除所有高亮
            Object.values(fieldLayers).forEach(layer => {
                if (layer && layer.setStyle) {
                    layer.setStyle({ weight: 2, opacity: 0.6 });
                }
            });
            
            // 高亮当前地块
            const layer = fieldLayers[fieldId];
            if (layer && layer.setStyle) {
                layer.setStyle({ weight: 4, opacity: 1.0 });
            }
        }
        
        // 开始手动绘制路径
        function startManualDraw(fieldId) {
            const pathName = document.getElementById('field-path-name').value;
            const pathType = document.getElementById('field-path-type').value;
            
            if (!pathName) {
                showToast('请先输入路径名称', 'warning');
                return;
            }
            
            // 在关闭对话框之前先保存路径信息
            window.tempPathInfo = { name: pathName, type: pathType, fieldId: fieldId };
            console.log('[绘制] 保存路径信息:', window.tempPathInfo);
            
            closeModal();
            
            currentDrawingFieldId = fieldId;
            isDrawingMode = true;
            drawingPoints = [];
            
            console.log('[绘制] ===== 开始绘制模式 =====');
            console.log('[绘制] 路径名称:', pathName);
            console.log('[绘制] 路径类型:', pathType);
            console.log('[绘制] isDrawingMode =', isDrawingMode);
            console.log('[绘制] 地块图层数量:', Object.keys(fieldLayers).length);
            console.log('[绘制] 中心标记数量:', Object.keys(fieldCenterMarkers).length);
            
            // 关闭所有打开的popup
            if (gisMap) {
                gisMap.closePopup();
            }
            
            // 移除所有地块polygon图层
            let removedLayers = 0;
            Object.values(fieldLayers).forEach(layer => {
                if (layer && gisMap) {
                    gisMap.removeLayer(layer);
                    removedLayers++;
                }
            });
            console.log('[绘制] 移除了', removedLayers, '个地块图层');
            
            // 移除所有地块中心标记
            let removedMarkers = 0;
            Object.values(fieldCenterMarkers).forEach(marker => {
                if (marker && gisMap) {
                    gisMap.removeLayer(marker);
                    removedMarkers++;
                }
            });
            console.log('[绘制] 移除了', removedMarkers, '个中心标记');
            
            // 显示绘制提示
            const indicator = document.getElementById('draw-indicator');
            if (indicator) {
                indicator.style.display = 'block';
                indicator.querySelector('#draw-count').textContent = '0';
            }
            
            showToast(`开始绘制路径：${pathName}`, 'info');
            console.log('[绘制] 绘制模式已启动，现在点击地图应该能添加点了');
        }
        
        // 查看地块的所有路径
        function viewFieldPaths(fieldId) {
            console.log('[查看路径] 查看地块路径:', fieldId);
            
            fetch(`/api/gis/field/${fieldId}`)
                .then(r => r.json())
                .then(field => {
                    if (field.error) {
                        showToast('地块数据未找到', 'warning');
                        return;
                    }
                    
                    console.log('[查看路径] 地块数据:', field);
                    console.log('[查看路径] 路径列表:', field.paths);
                    
                    // 聚焦到该地块
                    if (field.boundary && field.boundary.length > 0) {
                        const bounds = L.latLngBounds(field.boundary);
                        gisMap.fitBounds(bounds, { padding: [50, 50] });
                    }
                    
                    // 高亮显示该地块
                    highlightField(fieldId);
                    
                    // 获取该地块的所有路径
                    const pathIds = field.paths || [];
                    
                    if (pathIds.length === 0) {
                        showToast('该地块还没有路径，请先绘制路径', 'info');
                        console.log('[查看路径] 该地块没有关联路径');
                        return;
                    }
                    
                    // 隐藏所有其他路径
                    hideAllPaths();
                    
                    // 加载并显示该地块的路径
                    loadAndShowFieldPaths(pathIds, field);
                })
                .catch(e => {
                    console.error('[GIS] 获取地块失败:', e);
                    showToast('获取地块信息失败', 'danger');
                });
        }
        
        // 加载并显示地块的路径
        function loadAndShowFieldPaths(pathIds, field) {
            // 如果没有选择地图，尝试从默认地图加载
            const mapId = currentMapId || 'MAP-001';
            
            console.log(`[查看路径] 从地图${mapId}加载路径`);
            
            fetch(`/api/gis/map/${mapId}/paths`)
                .then(r => r.json())
                .then(data => {
                    const allPaths = data.paths || [];
                    console.log(`[查看路径] 地图中共有${allPaths.length}条路径`);
                    
                    // 加载该地块的路径到pathLayers
                    pathIds.forEach(pathId => {
                        const pathData = allPaths.find(p => p.id === pathId);
                        if (pathData) {
                            console.log(`[查看路径] 找到路径${pathId}:`, pathData);
                            // 如果路径不在pathLayers中，添加进去
                            if (!pathLayers[pathId]) {
                                displayPathOnMap(pathData, false);
                            }
                            // 显示路径
                            showPathOnMap(pathId);
                        } else {
                            console.log(`[查看路径] 路径${pathId}未找到`);
                        }
                    });
                    
                    // 显示路径列表弹窗
                    showFieldPathsModal(field, pathIds);
                })
                .catch(e => {
                    console.error('[查看路径] 加载路径失败:', e);
                    showToast('加载路径失败', 'danger');
                });
        }
        
        // 隐藏所有路径
        function hideAllPaths() {
            Object.keys(pathLayers).forEach(pathId => {
                const layer = pathLayers[pathId];
                if (layer && gisMap && visiblePaths.has(pathId)) {
                    gisMap.removeLayer(layer);
                    visiblePaths.delete(pathId);
                }
            });
        }
        
        // 显示指定路径
        function showPathOnMap(pathId) {
            const layer = pathLayers[pathId];
            if (layer && gisMap) {
                gisMap.addLayer(layer);
                visiblePaths.add(pathId);
            }
        }
        
        // 显示地块路径列表
        function showFieldPathsModal(field, pathIds) {
            // 这里需要获取所有路径数据
            // 暂时用占位数据，后续从API获取
            const html = `
                <div style="background: #f8f9fa; padding: 15px; border-radius: 6px; margin-bottom: 15px;">
                    <div style="font-weight: 600; color: #2c3e50; margin-bottom: 8px;">${field.name}</div>
                    <div style="font-size: 12px; color: #7f8c8d;">编号: ${field.id} | 面积: ${field.area}亩 | 路径数量: ${pathIds.length}条</div>
                </div>
                
                <div style="margin-bottom: 15px;">
                    <div style="font-size: 13px; color: #2c3e50; font-weight: 600; margin-bottom: 10px;">关联路径列表</div>
                    <div id="field-paths-container" style="max-height: 350px; overflow-y: auto;">
                        ${pathIds.map((pathId, i) => `
                            <div style="background: white; padding: 12px; border-radius: 4px; margin-bottom: 8px; border-left: 3px solid #27ae60; display: flex; justify-content: space-between; align-items: center;">
                                <div>
                                    <div style="font-weight: 600; color: #2c3e50; font-size: 13px; margin-bottom: 3px;">${pathId}</div>
                                    <div style="font-size: 11px; color: #7f8c8d;">点击查看详情</div>
                                </div>
                                <div style="display: flex; gap: 6px;">
                                    <button onclick="togglePathVisibility('${pathId}'); event.stopPropagation();" class="btn btn-primary" style="padding: 6px 12px; font-size: 11px;">显示/隐藏</button>
                                    <button onclick="deletePathFromField('${field.id}', '${pathId}'); event.stopPropagation();" class="btn btn-danger" style="padding: 6px 12px; font-size: 11px;">删除</button>
                                </div>
                            </div>
                        `).join('')}
                    </div>
                </div>
                
                <div class="modal-buttons">
                    <button class="modal-btn btn-success" onclick="drawPathForField('${field.id}')">新增路径</button>
                    <button class="modal-btn btn-default" onclick="closeModal()">关闭</button>
                </div>
            `;
            
            showModal('地块路径管理', html);
        }
        
        // 切换路径显示/隐藏
        let visiblePaths = new Set();
        function togglePathVisibility(pathId) {
            const layer = pathLayers[pathId];
            if (!layer || !gisMap) {
                showToast('路径未找到', 'warning');
                return;
            }
            
            if (visiblePaths.has(pathId)) {
                // 隐藏路径
                gisMap.removeLayer(layer);
                visiblePaths.delete(pathId);
                showToast(`路径 ${pathId} 已隐藏`, 'info');
            } else {
                // 显示路径
                gisMap.addLayer(layer);
                visiblePaths.add(pathId);
                showToast(`路径 ${pathId} 已显示`, 'success');
            }
        }
        
        // 从地块删除路径
        function deletePathFromField(fieldId, pathId) {
            if (!confirm(`确定从地块中删除路径 ${pathId} 吗？`)) {
                return;
            }
            
            // 这里需要调用API删除路径与地块的关联
            showToast(`路径 ${pathId} 已从地块中移除`, 'success');
            closeModal();
            
            // 刷新地块数据
            loadFieldsData();
        }
        
        // GPS记录功能（为指定地块）
        function startGPSRecordForField(fieldId) {
            const pathName = document.getElementById('field-path-name').value;
            if (!pathName) {
                showToast('请先输入路径名称', 'warning');
                return;
            }
            
            closeModal();
            currentDrawingFieldId = fieldId;
            showToast(`开始GPS记录：${pathName}（为地块 ${fieldId}）`, 'success');
            
            // 调用原有的GPS记录功能
            window.tempPathInfo = { name: pathName, fieldId: fieldId };
        }
        
        // AI规划功能（为指定地块）
        function startAIPlanningForField(fieldId) {
            const pathName = document.getElementById('field-path-name').value;
            if (!pathName) {
                showToast('请先输入路径名称', 'warning');
                return;
            }
            
            closeModal();
            currentDrawingFieldId = fieldId;
            
            fetch(`/api/gis/field/${fieldId}`)
                .then(r => r.json())
                .then(field => {
                    showToast(`正在为地块 ${field.name} 进行AI路径规划...`, 'info');
                    // 这里可以调用AI规划功能
                    autoPlanning();
                })
                .catch(e => {
                    console.error('[GIS] AI规划失败:', e);
                    showToast('AI规划失败', 'danger');
                });
        }
        
        // 取消绘制
        function cancelDrawing() {
            isDrawingMode = false;
            drawingPoints = [];
            
            // 恢复所有地块图层的交互和popup
            restoreFieldInteraction();
            
            const indicator = document.getElementById('draw-indicator');
            if (indicator) indicator.style.display = 'none';
            
            // 清除绘制线
            if (currentDrawing && gisMap) {
                gisMap.removeLayer(currentDrawing);
                currentDrawing = null;
            }
            
            // 清除所有临时标记点
            if (gisMap && drawingMarkers) {
                drawingMarkers.forEach(m => gisMap.removeLayer(m));
            }
            drawingMarkers = [];
            
            console.log('[绘制] 已恢复地块交互，退出绘制模式');
            showToast('已退出绘制模式', 'info');
        }
        
        // 更新地块的路径列表
        function updateFieldPaths(fieldId, pathId) {
            // 获取地块数据
            fetch(`/api/gis/field/${fieldId}`)
                .then(r => r.json())
                .then(field => {
                    if (field.error) {
                        console.error('[GIS] 地块不存在:', fieldId);
                        return;
                    }
                    
                    // 确保paths数组存在
                    if (!field.paths) {
                        field.paths = [];
                    }
                    
                    // 添加路径ID（避免重复）
                    if (!field.paths.includes(pathId)) {
                        field.paths.push(pathId);
                        console.log(`[GIS] 添加路径${pathId}到地块${fieldId}, 当前paths:`, field.paths);
                        
                        // 更新地块数据
                        return fetch(`/api/gis/field/${fieldId}/update`, {
                            method: 'POST',
                            headers: {'Content-Type': 'application/json'},
                            body: JSON.stringify({ paths: field.paths })
                        });
                    } else {
                        console.log(`[GIS] 路径${pathId}已存在于地块${fieldId}中`);
                    }
                })
                .then(r => {
                    if (r) return r.json();
                })
                .then(result => {
                    if (result && result.success) {
                        console.log(`[GIS] 地块${fieldId}的路径列表已更新`);
                        // 刷新地块数据以更新左侧列表的路径计数
                        loadFieldsData();
                    }
                })
                .catch(e => {
                    console.error('[GIS] 更新地块路径失败:', e);
                });
        }
        
        // 恢复地块交互功能
        function restoreFieldInteraction() {
            // 清空旧的地块图层引用
            Object.keys(fieldLayers).forEach(key => {
                delete fieldLayers[key];
            });
            
            // 清空旧的中心标记引用
            Object.keys(fieldCenterMarkers).forEach(key => {
                delete fieldCenterMarkers[key];
            });
            
            // 重新加载地块数据，重新添加到地图
            loadFieldsData();
        }
        
        // 加载地块数据
        function loadFieldsData() {
            fetch('/api/gis/fields')
                .then(r => r.json())
                .then(data => {
                    const fields = data.fields || [];
                    console.log('[GIS] 地块数据加载成功:', fields.length);
                    
                    // 只在非绘制模式下显示地块边界
                    if (!isDrawingMode && !isDrawingFieldMode) {
                        fields.forEach(field => {
                            displayFieldOnMap(field);
                        });
                        console.log('[GIS] 地块已显示到地图');
                    } else {
                        console.log('[GIS] 绘制模式下，跳过地块显示');
                    }
                    
                    // 更新左侧地块列表
                    updateFieldsList(fields);
                })
                .catch(e => {
                    console.error('[GIS] 地块数据加载失败:', e);
                });
        }
        
        // 更新地块列表
        function updateFieldsList(fields) {
            const fieldListHtml = fields.map((field, i) => {
                const colors = {
                    '已完成': { bg: '#e8f5e9', border: '#27ae60', text: '#27ae60' },
                    '进行中': { bg: '#e3f2fd', border: '#3498db', text: '#3498db' },
                    '待作业': { bg: '#fef5e7', border: '#f39c12', text: '#f39c12' }
                };
                const style = colors[field.status] || colors['待作业'];
                const pathCount = (field.paths && field.paths.length) || 0;
                
                return `
                    <div style="background: ${style.bg}; padding: 10px 10px 8px 10px; border-radius: 4px; margin-bottom: 6px; border-left: 3px solid ${style.border}; position: relative;">
                        <div style="cursor: pointer;" onclick="viewFieldDetail('${field.id}')">
                            <div style="font-weight: 600; color: ${style.text}; font-size: 13px; margin-bottom: 3px;">${field.id}</div>
                            <div style="font-size: 11px; color: #2c3e50; margin-bottom: 5px;">${field.name} | ${field.area}亩 | ${pathCount}条路径</div>
                            <div style="background: #ecf0f1; height: 4px; border-radius: 2px; overflow: hidden;">
                                <div style="background: ${style.border}; height: 100%; width: ${field.progress}%;"></div>
                            </div>
                            <div style="font-size: 10px; color: ${style.text}; margin-top: 3px;">${field.status} ${field.progress}%</div>
                        </div>
                        <div style="position: absolute; top: 8px; right: 8px; display: flex; gap: 4px;">
                            <button onclick="editFieldModal('${field.id}'); event.stopPropagation();" style="padding: 3px 8px; background: #3498db; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 10px;">编辑</button>
                            <button onclick="deleteFieldFromMap('${field.id}'); event.stopPropagation();" style="padding: 3px 8px; background: #e74c3c; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 10px;">删除</button>
                        </div>
                        <div style="margin-top: 6px; padding-top: 6px; border-top: 1px solid rgba(0,0,0,0.05); display: flex; gap: 4px;">
                            <button onclick="drawPathForField('${field.id}'); event.stopPropagation();" style="flex: 1; padding: 4px 8px; background: #27ae60; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 10px; font-weight: 600;">绘制路径</button>
                            <button onclick="viewFieldPaths('${field.id}'); event.stopPropagation();" style="flex: 1; padding: 4px 8px; background: #9b59b6; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 10px; font-weight: 600;">查看路径</button>
                        </div>
                    </div>
                `;
            }).join('');
            
            const container = document.getElementById('gis-field-list');
            if (container) {
                container.innerHTML = fieldListHtml || '<div style="color: #7f8c8d; padding: 15px; text-align: center; font-size: 12px;">暂无地块</div>';
            }
        }
        
        // 在地图上显示路径（修改为默认不显示）
        function displayPathOnMap(path, autoShow = false) {
            if (!gisMap || !path.points || path.points.length === 0) return;
            
            const color = path.status === '已验证' ? '#27ae60' : '#f39c12';
            
            const polyline = L.polyline(path.points, {
                color: color,
                weight: 3,
                opacity: 0.8
            });
            
            // 只有当autoShow为true时才添加到地图
            if (autoShow) {
                polyline.addTo(gisMap);
                visiblePaths.add(path.id);
            }
            
            polyline.bindPopup(`
                <strong>${path.name}</strong><br>
                编号: ${path.id}<br>
                类型: ${path.type}<br>
                点数: ${path.points.length}<br>
                状态: ${path.status}
            `);
            
            pathLayers[path.id] = polyline;
            console.log(`[GIS] 创建路径图层: ${path.id}，${autoShow ? '已显示' : '未显示'}`);
        }
        
        // 在地图上显示地块
        function displayFieldOnMap(field) {
            if (!gisMap || !field.boundary || field.boundary.length === 0) return;
            
            // 如果正在绘制，不显示地块
            if (isDrawingMode || isDrawingFieldMode) {
                console.log(`[GIS] 绘制模式下，跳过显示地块: ${field.id}`);
                return;
            }
            
            const color = field.status === '已完成' ? '#27ae60' : 
                         field.status === '进行中' ? '#3498db' : '#f39c12';
            
            const polygon = L.polygon(field.boundary, {
                color: color,
                weight: 2,
                fillColor: color,
                fillOpacity: 0.15,
                interactive: true,
                bubblingMouseEvents: true  // 允许事件冒泡到地图
            }).addTo(gisMap);
            
            // 绑定popup内容
            polygon.bindPopup(`
                <strong>${field.name}</strong><br>
                编号: ${field.id}<br>
                面积: ${field.area} 亩<br>
                进度: ${field.progress}%<br>
                状态: ${field.status}
            `);
            
            // 添加中心标记
            const centerMarker = L.circleMarker(field.center, {
                radius: 6,
                fillColor: color,
                color: '#fff',
                weight: 2,
                fillOpacity: 0.9,
                interactive: true,
                bubblingMouseEvents: true
            }).addTo(gisMap);
            
            centerMarker.bindPopup(`<strong>${field.name}</strong><br>${field.area}亩`);
            
            // 保存polygon和centerMarker
            fieldLayers[field.id] = polygon;
            fieldCenterMarkers[field.id] = centerMarker;  // 保存中心标记
            console.log(`[GIS] 显示地块: ${field.id}`);
        }
        
        // 计算路径长度（米）
        function calculatePathLength(points) {
            if (points.length < 2) return 0;
            
            let totalDistance = 0;
            for (let i = 1; i < points.length; i++) {
                const p1 = points[i - 1];
                const p2 = points[i];
                const lat1 = p1.lat || p1[0];
                const lng1 = p1.lng || p1[1];
                const lat2 = p2.lat || p2[0];
                const lng2 = p2.lng || p2[1];
                
                // Haversine公式计算两点距离
                const R = 6371000; // 地球半径（米）
                const dLat = (lat2 - lat1) * Math.PI / 180;
                const dLng = (lng2 - lng1) * Math.PI / 180;
                const a = Math.sin(dLat/2) * Math.sin(dLat/2) +
                         Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
                         Math.sin(dLng/2) * Math.sin(dLng/2);
                const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
                totalDistance += R * c;
            }
            
            return totalDistance;
        }
        
        
        function resetMap() {

            if (map) {
            map.setView([23.757, 109.166], 17);

            showToast('地图已重置', 'success');

            }
        }
        
        // 加载地块到首页地图
        function loadFieldsToHomeMap() {
            fetch('/api/gis/fields')
                .then(r => r.json())
                .then(data => {
                    const fields = data.fields || [];
                    console.log(`[首页地图] 加载 ${fields.length} 个地块`);
                    
                    fields.forEach(field => {
                        if (field.boundary && field.boundary.length > 0) {
                            const layer = L.polygon(field.boundary, {
                                color: '#3498db',
                                fillColor: '#3498db',
                                fillOpacity: 0.15,
                                weight: 2
                            }).addTo(map);
                            
                            layer.bindPopup(`
                                <div style="font-weight: 600; margin-bottom: 5px;">${field.name}</div>
                                <div style="font-size: 12px; color: #7f8c8d;">面积: ${field.area} 亩</div>
                            `);
                            
                            homeMapFieldLayers[field.id] = layer;
                        }
                    });
                })
                .catch(e => console.error('[首页地图] 加载地块失败:', e));
        }
        
        // 在首页地图显示任务路径
        function showTaskPathOnHomeMap(pathId, pathName) {
            fetch(`/api/gis/map/MAP-001/paths`)
                .then(r => r.json())
                .then(data => {
                    const path = data.paths.find(p => p.id === pathId);
                    if (!path) {
                        console.error('[首页地图] 路径不存在:', pathId);
                        return;
                    }
                    
                    // 移除旧的路径图层
                    if (homeMapPathLayers[pathId]) {
                        map.removeLayer(homeMapPathLayers[pathId]);
                    }
                    
                    // 添加新的路径图层
                    const pathLayer = L.polyline(path.points, {
                        color: '#e74c3c',
                        weight: 4,
                        opacity: 0.8
                    }).addTo(map);
                    
                    pathLayer.bindPopup(`
                        <div style="font-weight: 600; margin-bottom: 5px;">${pathName}</div>
                        <div style="font-size: 12px; color: #7f8c8d;">
                            ${path.point_count} 点 · ${path.length} m
                        </div>
                    `);
                    
                    homeMapPathLayers[pathId] = pathLayer;
                    
                    // 调整地图视角到路径
                    map.fitBounds(pathLayer.getBounds(), { padding: [50, 50] });
                    
                    console.log(`[首页地图] 显示路径: ${pathName}`);
                })
                .catch(e => console.error('[首页地图] 加载路径失败:', e));
        }
        
        // 清除首页地图的任务路径
        function clearTaskPathsOnHomeMap() {
            Object.values(homeMapPathLayers).forEach(layer => {
                if (map) map.removeLayer(layer);
            });
            homeMapPathLayers = {};
            console.log('[首页地图] 已清除所有任务路径');
        }

        
        
        // GPS更新

        function updateGPS() {

            fetch('/api/gps').then(r => r.json()).then(data => {

                if (data.connected && data.latitude != 0) {

                    const pos = [data.latitude, data.longitude];

                    marker.setLatLng(pos);

                    map.setView(pos, map.getZoom());

                    trackPoints.push(pos);

                    if (trackPoints.length > 100) trackPoints.shift();

                    trackPath.setLatLngs(trackPoints);

                    marker.bindPopup(`GPS: ${data.satellites}颗卫星<br>${data.fix_type}`);

                }

            });

        }

        
        
        // WASD控制

        document.addEventListener('keydown', (e) => {

            const k = e.key.toLowerCase();

            if (!activeKeys.has(k)) {

                activeKeys.add(k);

                if (k === 'w') { wasdState.forward = 15; sendWASD(); }

                if (k === 's') { wasdState.forward = -15; sendWASD(); }

                if (k === 'a' || k === 'arrowleft') { wasdState.turn = -8; sendWASD(); }

                if (k === 'd' || k === 'arrowright') { wasdState.turn = 8; sendWASD(); }

                if (k === ' ') {

                    e.preventDefault();

                    wasdState.forward = 0;

                    wasdState.turn = 0;

                    sendWASD();

                    showToast('紧急停止', 'danger');

                }

            }

        });

        
        
        document.addEventListener('keyup', (e) => {

            const k = e.key.toLowerCase();

            activeKeys.delete(k);

            if (k === 'w' || k === 's') { wasdState.forward = 0; sendWASD(); }

            if (k === 'a' || k === 'd' || k === 'arrowleft' || k === 'arrowright') { wasdState.turn = 0; sendWASD(); }

        });

        
        
        function sendWASD() {

            document.getElementById('fwd-val').textContent = wasdState.forward;

            document.getElementById('turn-val').textContent = wasdState.turn;

            socket.emit('movement_control', wasdState);

        }

        
        
        // 传感器数据

        socket.on('sensor_data', function(data) {

            if (data.sensors) {

                const s = data.sensors;

                if (s.generator_voltage != null) {

                    document.getElementById('voltage').textContent = (s.generator_voltage/100).toFixed(2) + 'V';

                }

                if (s.generator_current != null) {

                    document.getElementById('current').textContent = (s.generator_current/100).toFixed(2) + 'A';

                }

                if (s.generator_power != null) {

                    document.getElementById('power').textContent = s.generator_power + 'W';

                }

                if (s.fuel_level != null) {

                    document.getElementById('fuel').textContent = s.fuel_level + '%';

                    document.getElementById('fuel-bar').style.width = s.fuel_level + '%';

                    document.getElementById('fuel-bar').textContent = s.fuel_level + '%';

                }

                document.getElementById('modbus').textContent = '正常';

            }

        });
        

        

        // 弹窗系统（带动画）
        function showModal(title, body) {

            document.getElementById('modal-title').textContent = title;

            document.getElementById('modal-body').innerHTML = body;

            
            const overlay = document.getElementById('overlay');
            const modal = document.getElementById('modal');
            
            overlay.style.display = 'block';
            modal.style.display = 'block';
            
            // 触发重绘，确保动画生效
            setTimeout(() => {
                overlay.classList.add('show');
                modal.classList.add('show');
            }, 10);
        }

        
        
        // 右侧面板展开/收起
        function toggleRightPanel() {
            const panel = document.getElementById('rightPanel');
            const icon = document.getElementById('toggleIcon');
            const title = document.getElementById('panelTitle');
            
            if (panel.classList.contains('expanded')) {
                // 收起
                panel.classList.remove('expanded');
                icon.textContent = '展开';
                title.textContent = '机器人 GZJY001 系统状态';
            } else {
                // 展开
                panel.classList.add('expanded');
                icon.textContent = '收起';
                title.textContent = '所有机器人系统状态总览';
            }
        }

        function closeModal() {

            const overlay = document.getElementById('overlay');
            const modal = document.getElementById('modal');
            
            overlay.classList.remove('show');
            modal.classList.remove('show');
            
            // 等待动画完成后隐藏
            setTimeout(() => {
                overlay.style.display = 'none';
                modal.style.display = 'none';
            }, 400);
        }

        
        
        // Toast提示

        function showToast(msg, type = 'info') {

            const colors = {

                success: '#27ae60',

                warning: '#f39c12',

                danger: '#e74c3c',

                info: '#3498db'

            };

            const toast = document.createElement('div');

            toast.className = 'toast';

            toast.style.borderColor = colors[type];

            toast.textContent = msg;

            document.body.appendChild(toast);

            setTimeout(() => toast.remove(), 2000);

        }

        
        
        // ===== 以下引入弹窗功能 =====

    </script>

    <!-- modals.js 在内联脚本之后加载，但其中的 startManualDraw 等函数已被注释掉 -->
    <!-- 这样内联脚本中定义的函数不会被覆盖 -->
    <script src="/static/modals.js?v=20251024004"></script>

</body>

</html>





